This is a migrated thread and some comments may be shown as answers.

How to pass content of edited node as parameter

5 Answers 109 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
hokushin
Top achievements
Rank 1
hokushin asked on 04 May 2012, 04:22 PM
Hello,

I am developing Silverlight application using MVVM design pattern and Telerik TreeView control. I want to pass the content of the Edited Node to ViewModel class. I am trying to do it like below. It doesn't work though. Please advise.

<telerikNavigation:RadTreeView Grid.Row="1" x:Name="tree" IsEditable="True" BorderThickness="1" BorderBrush="#FF9ABFE5" Margin="3">

            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Edited">
                    <i:InvokeCommandAction Command="{Binding ItemEditedCommand}" CommandParameter="{Binding CurrentTerritory, Mode=OneWay" />
                </i:EventTrigger>
            </i:Interaction.Triggers>

            <telerikNavigation:RadTreeView.ItemTemplate>
                <telerik:HierarchicalDataTemplate ItemsSource="{Binding Childs}"  >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
                    </StackPanel>
                </telerik:HierarchicalDataTemplate>
            </telerikNavigation:RadTreeView.ItemTemplate>
            <telerikNavigation:RadTreeView.ItemContainerStyle>
                <Style TargetType="telerikNavigation:RadTreeViewItem">
                    <Setter Property="HorizontalAlignment" Value="Stretch"/>
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    <Setter Property="IsExpanded" Value="True" />
                </Style>
            </telerikNavigation:RadTreeView.ItemContainerStyle>
            <telerikNavigation:RadTreeView.ItemEditTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Name, Mode=TwoWay}" >
                    </TextBox>
                </DataTemplate>
            </telerikNavigation:RadTreeView.ItemEditTemplate>
        </telerikNavigation:RadTreeView>



public TerritoryListVM(IUIMessageBox uiMessageBox, AsyncCaller asyncCaller)
        {
            ItemEditedCommand = new DelegateCommand((a) => { this.ItemEditedCommandAction(a); }, (p) => { return true; });

            LoadData();
        }

public const string PnCurrentTerritory = "CurrentTerritory";
        private TerritoryDB _currentTerritory;
        public virtual TerritoryDB CurrentTerritory
        {
            get
            {
                return _currentTerritory;
            }
            set
            {
                if (_currentTerritory != value)
                {
                    _currentTerritory = value;
                    OnPropertyChanged(PnCurrentTerritory);
                }
            }
        }

public DelegateCommand ItemEditedCommand { get; set; }

        private void ItemEditedCommandAction(object param)
        {
            string filter = param as string;
.......................................
         }

5 Answers, 1 is accepted

Sort by
0
hokushin
Top achievements
Rank 1
answered on 05 May 2012, 12:28 PM
I've figured out the problem with GalaSoft.mvvmlight. The question is how can I persist the node in edit mode while performing node validation via WCF service
0
Petar Mladenov
Telerik team
answered on 09 May 2012, 07:30 AM
Hello Hokushin,

 Could you please elaborate more on your last question? This way we would be better able to advice you.

Regards,
Petar Mladenov
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

0
hokushin
Top achievements
Rank 1
answered on 10 May 2012, 06:58 AM
Actually, I found the way to persist the node in edit node. Please see below how I did it

private GalaSoft.MvvmLight.Command.RelayCommand<RadTreeViewItemEditedEventArgs> myCommand;

        public GalaSoft.MvvmLight.Command.RelayCommand<RadTreeViewItemEditedEventArgs> MyCommand
        {
            get
            {
                return myCommand;
            }
        }

private void myCommand_Execute(RadTreeViewItemEditedEventArgs e)
        {
            RadTreeViewItem clickedItem = e.OriginalSource as RadTreeViewItem;
            _asyncCaller.Call(c => _context.BeginGetDublicateCountForTerritory(CurrentTerritory, c, null), _context.EndGetDublicateCountForTerritory, cnt =>
            {
                if (cnt)
                {
                    // node in edit mode
                    (e.Source as RadTreeViewItem).IsInEditMode = true;
                    (e.Source as RadTreeViewItem).Focus();
                    (e.Source as RadTreeViewItem).Background = new SolidColorBrush(Colors.Red);
                    //_uiMessageBox.Show("Данная территория уже уже добавлена в базу данных.");
                }
                else
                {
                    // 5.5.2012 сохраняем изменения в базу данных
                    (e.Source as RadTreeViewItem).IsInEditMode = false;
                    _asyncCaller.Call(c => _context.BeginModifyTerritories(_collectionInspector.GetDiff(), c, null), _context.EndModifyTerritories, null);
                }

            });
        }

Now I want to apply some validation style to the node (instead of MessageBox) I've implemented INotifyDataErrorInfo interface for the node but it doesn't work:

<telerikNavigation:RadTreeView.ItemEditTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=True,ValidatesOnNotifyDataErrors=True}" />             
                </DataTemplate>
            </telerikNavigation:RadTreeView.ItemEditTemplate>

So I am thinking of looping through the control tree and then using ControlValidationHelper helper class: http://stackoverflow.com/questions/4158503/set-validation-message-on-control-manually. But it's time consuming. So I wish the RadTreeView had some built in validation stuff. I've drilled down through the forum but failed to find what I needed.
0
hokushin
Top achievements
Rank 1
answered on 11 May 2012, 01:19 PM
Hi Petar,
How are you doing? I hope that you are well.
So, I've created a couple of methods below. Everything works fine with DataForm:

private void ValidateTerritory()
{
   if (string.IsNullOrEmpty(this.TerritoryDB.Name))
   {
      Extensions.ValidateField<TextBox>(this.addTerritoryDataForm, "Name", ErrorResources.RequiredField);
   }
   else
   {
      Extensions.ClearField<TextBox>(this.addTerritoryDataForm, "ValidateName");
   }

How can I access the item in the ItemEditTemplate on the RadTreeView ?

<telerikNavigation:RadTreeView.ItemEditTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding ValidatedName, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
                </DataTemplate>
            </telerikNavigation:RadTreeView.ItemEditTemplate>

I\ve tried the approach below etc but it didn't make the trick:

FrameworkElement element = e.OriginalSource as FrameworkElement;
Extensions.ValidateField<RadTreeViewItem>(element, "ValidateName", ErrorResources.RequiredField);

Your comments and suggestions would be greatly appreciated.

public static class Extensions
    {
        public static T FindChild<T>(DependencyObject parent, string childName)
   where T : DependencyObject
        {
            // Confirm parent and childName are valid.
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                // If the child is not of the request child type child
                T childType = child as T;
                if (childType == null)
                {
                    // recursively drill down the tree
                    foundChild = FindChild<T>(child, childName);

                    // If the child is found, break so we do not overwrite the found child.
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // If the child's name is set for search
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        // if the child's name is of the request name
                        foundChild = (T)child;
                        break;
                    }
                }
                else
                {
                    // child element found.
                    foundChild = (T)child;
                    break;
                }
            }

            return foundChild;
        }


        // http://stackoverflow.com/questions/636383/wpf-ways-to-find-controls
        public static void ValidateField<T>(DependencyObject dobj, string strField, string strErrorMessage)
            where T : DependencyObject
        {
            object foundControl = FindChild<T>(dobj, strField);

            if (foundControl is T)
            {
                // Following executed if Text element was found.

                var controlToValidate = foundControl as FrameworkElement;

                var helper = new ControlValidationHelper() { Message = strErrorMessage };
                controlToValidate.SetBinding(Control.TagProperty, new Binding("ValidationError")
                {
                    Mode = BindingMode.TwoWay,
                    NotifyOnValidationError = true,
                    ValidatesOnDataErrors = true,
                    UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
                    Source = helper
                });
                controlToValidate.GetBindingExpression(Control.TagProperty).UpdateSource();
            }
        }

        public static void ClearField<T>(DependencyObject dobj, string strFieldName)
            where T : DependencyObject
        {
            object foundControl = FindChild<T>(dobj, strFieldName);

            if (foundControl is T)
            {
                // Following executed if Text element was found.
                var controlToClear = foundControl as FrameworkElement;

                BindingExpression b = controlToClear.GetBindingExpression(Control.TagProperty);
                if (b != null)
                {
                    ((ControlValidationHelper)b.DataItem).Message = null;
                    b.UpdateSource();
                }
            }
        } 

    }
0
Petar Mladenov
Telerik team
answered on 14 May 2012, 09:02 AM
Hi V A,

 As I managed to understand, you need to access in code behind the TextBox from the ItemEditTemplate.
If so, have you tried the Telerik's Extension method ChildrenOfType<> from Telerik.Windows.Controls namespace ?

All the best,
Petar Mladenov
the Telerik team

Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Tags
TreeView
Asked by
hokushin
Top achievements
Rank 1
Answers by
hokushin
Top achievements
Rank 1
Petar Mladenov
Telerik team
Share this question
or