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

How to determine which item was checked?

6 Answers 605 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Jeramy
Top achievements
Rank 1
Jeramy asked on 04 Dec 2015, 10:52 PM

I am using the checkboxes in a RadTreeView. The treeview items are bound to my own heirarchical type called TreeNode. When an item is checked how do I determine which TreeNode object was checked?

Currently I am using a command to handle the IsChecked event of the control. I am passing the event arguments to the command. I can get access to all the checked items in the tree as TreeNodes, but am at a loss as to which one was actually last checked.

 <telerik:RadTreeView x:Name="TreePermissions"
                                                 DockPanel.Dock="Top"
                                                 MinHeight="50"
                                                 BorderBrush="Black"
                                                 BorderThickness="1"
                                                 Margin="5,0,5,0"
                                                 IsOptionElementsEnabled="True"
                                                 ItemsSource="{Binding UserPermissions}"
                                                 ItemPrepared="TreePermissions_ItemPrepared">
                                
                                <telerik:EventToCommandBehavior.EventBindings>
                                    <telerik:EventBinding Command="{Binding PermissionCheckedCommand}" EventName="Checked"
                                                          PassEventArgsToCommand="True" />
                                </telerik:EventToCommandBehavior.EventBindings>
                                
                                <telerik:RadTreeView.ItemContainerStyle>
                                    <Style TargetType="{x:Type telerik:RadTreeViewItem}">
                                        <Setter Property="IsExpanded" Value="True"/>
                                        <Setter Property="IsChecked" Value="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}"/>
                                        <Setter Property="IsEnabled" Value="{Binding IsEnabled, UpdateSourceTrigger=PropertyChanged}"/>
                                    </Style>
                                </telerik:RadTreeView.ItemContainerStyle>
                            </telerik:RadTreeView>

 

private void OnPermissionChecked(object obj)
        {
            var args = obj as Telerik.Windows.Controls.RadTreeViewCheckEventArgs;
            Telerik.Windows.Controls.RadTreeViewItem item = args.OriginalSource as Telerik.Windows.Controls.RadTreeViewItem;
            // TreeNode node = item as TreeNode; // This does not work, cannot cast/convert for some reason
            Telerik.Windows.Controls.RadTreeView source = args.Source as Telerik.Windows.Controls.RadTreeView;
            if (source != null)
            {
                List<TreeNode> temp = source.CheckedItems.Cast<TreeNode>().ToList();
            }
        }

6 Answers, 1 is accepted

Sort by
0
Ivan
Telerik team
answered on 08 Dec 2015, 03:43 PM
Hello Jeramy,

We recommend to avoid using the RadTreeView's built-in checkbox functionality in a data binding scenario. Instead you can take a look at the  Implement a Tri-State CheckBox logic using MVVM help article. At the end of the article there is a link to the whole sample project, explained in it.

Please try this and let me know if it works for you.

Regards,
Ivan
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Jeramy
Top achievements
Rank 1
answered on 09 Dec 2015, 01:51 PM

1) What do you recommend avoiding the built-in check boxes? Why do they exist in a WPF control if you recommend avoiding them for data-binding?

2) In the example you provided, how do I determine which specific tree node was checked? I have two model classes that need to be maintained in congruence with the TreeNode class that was developed specifically to bind to the RadTreeView. So I need to intercept which node was checked and then apply changes to these other model classes. What do you recommend?

 Thanks!!!

0
Ivan
Telerik team
answered on 10 Dec 2015, 12:19 PM
Hi Jeramy,

1) What do you recommend avoiding the built-in check boxes? Why do they exist in a WPF control if you recommend avoiding them for data-binding?

The buit-in checkboxes of the TreeView are recommended to be used with small trees without virtualization or data binding. If there is virtualization (or data binding) they are highly not recommended.
In such scenarios we recommend using ItemTemplate with a CheckBox inside, as shown in the article I've sent you in my last reply. This is demonstrated also in the attached project. 

2)  In the example you provided, how do I determine which specific tree node was checked?

There is a simple example in the attached project demonstrating how to capture the checked item. Basically, you can get and save it in the setter of the IsChecked property of the treeitem's view model.

Regards,
Ivan
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Heiko
Top achievements
Rank 1
answered on 02 Dec 2016, 04:03 PM

I had a similar problem and found a nice solution to it. It is easier than what Telerik did in their example which I find too complicated. It's not the pure MVVM way but I think also a viable option.

My object is named "MailRecipient" and it has a IsSelected property as well as Name and EMail. First, I use a grouped QueryableCollectionView for my ItemsSource.

this.RecipientView = new QueryableCollectionView(this.NameList);
this.RecipientView.GroupDescriptors.Add(new GroupDescriptor()
    { Member = "Group", SortDirection = ListSortDirection.Ascending });

 

The RadTreeView is bound to the RecipientView's Group property and has a simple HierarchicalDataTemplate.

<DataTemplate x:Key="MailRecipientDataTemplate"  DataType="{x:Type localModels:MailRecipient}">
    <StackPanel Orientation="Horizontal">
         <TextBlock Text="{Binding Name}" />
         <TextBlock Text="{Binding EMail}" Margin="10 0 0 0" />
     </StackPanel>
 </DataTemplate>
<HierarchicalDataTemplate x:Key="MailTreeViewDataTemplate"
    ItemsSource="{Binding Items}"
    ItemTemplate="{StaticResource MailRecipientDataTemplate}">
    <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
         <TextBlock Text="{Binding Path=Name}" />
         <TextBlock Text="{Binding Path=ItemCount, StringFormat={} ({0} recipients)}" />
     </StackPanel>
</HierarchicalDataTemplate>

 

<telerik:RadTreeView ItemsSource="{Binding RecipientView.Groups}"
                     IsOptionElementsEnabled="True"
                     IsTriStateMode="True"
                     Checked="RadTreeView_Checked"
                     Unchecked="RadTreeView_Unchecked"
                     ItemTemplate="{StaticResource MailTreeViewDataTemplate}">
</telerik:RadTreeView>

Then in code behind I react to the Checked/Unchecked event of the RadTreeView. It is possible that these events get called several times when you click just one item: first because the group header element gets checked/unchecked, the other times for each of the child elements. When the RadTreeViewItem.Item property is the type of my MailRecipient class I set the IsSelected property of my object to the CheckState of the RadTreeViewItem which can bei On/Off/Indeterminate.

private void RadTreeView_Checked(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
    CheckAndUncheckItem(e.OriginalSource as RadTreeViewItem);
}
 
private void RadTreeView_Unchecked(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
    CheckAndUncheckItem(e.OriginalSource as RadTreeViewItem);
}
 
private void CheckAndUncheckItem(RadTreeViewItem treeViewItem)
{
    if (treeViewItem != null)
    {
        var recipient = treeViewItem.Item as MailRecipient;
        if (recipient != null)
        {
            recipient.IsSelected = treeViewItem.CheckState == ToggleState.On;
        }
    }
}

 

 

0
Lance | Senior Manager Technical Support
Telerik team
answered on 02 Dec 2016, 05:50 PM
Hi Heiko,

Yes, this is a good option for scenarios where you can use code-behind as we pass the TreeViewItem in the event args.

Thank you for sharing with the community!

Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Telerik UI for WPF is ready for Visual Studio 2017 RC! Learn more.
0
Heiko
Top achievements
Rank 1
answered on 05 Dec 2016, 09:12 AM

My solution has one small restriction. The child elements in the second level are checked only when they have been loaded at least once. This means if you click a parent element which has not been expanded before the child elements under this parent are not checked. What I do now is to "ExpandAll()" elements which is fine with just a few of them. I didn't find a method to "LoadAll()" children.

Regards
Heiko

Tags
TreeView
Asked by
Jeramy
Top achievements
Rank 1
Answers by
Ivan
Telerik team
Jeramy
Top achievements
Rank 1
Heiko
Top achievements
Rank 1
Lance | Senior Manager Technical Support
Telerik team
Share this question
or