How to pass content of edited node as parameter

6 posts, 0 answers
  1. hokushin
    hokushin avatar
    10 posts
    Member since:
    Sep 2012

    Posted 04 May 2012 Link to this post

    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;
    .......................................
             }
  2. hokushin
    hokushin avatar
    10 posts
    Member since:
    Sep 2012

    Posted 05 May 2012 Link to this post

    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
  3. DevCraft banner
  4. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 09 May 2012 Link to this post

    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 >>

  5. hokushin
    hokushin avatar
    10 posts
    Member since:
    Sep 2012

    Posted 10 May 2012 Link to this post

    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.
  6. hokushin
    hokushin avatar
    10 posts
    Member since:
    Sep 2012

    Posted 11 May 2012 Link to this post

    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();
                    }
                }
            } 

        }
  7. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 14 May 2012 Link to this post

    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 >>

Back to Top
DevCraft banner