How do I override item selection behaviors in RadtreeView?

2 posts, 0 answers
  1. Robert
    Robert avatar
    15 posts
    Member since:
    Mar 2013

    Posted 10 Apr 2013 Link to this post

    Hi,

    I'm working on a project where we have a RadTreeView and 3rd party CAD viewer control working off the same business objects (in this case the individual CAD entities). However the difference between the way the CAD viewer does selection and how the TreeView does selection will end up being confusing to customers, and the architect wants the treeview selection method to match the CAD's. For instance, in the CAD clicking on an entity, or drag-selection of multiple entities, without any key modifiers does not de-select already selected items. a key-modified-click or key-modified-drag-selection are what deselect the specific entities. This is the same as other CAD tools.

    So I have the task to override RadTreeView's selection methods to mimic these same selection behaviors - so that when you click on a treeviewitem it will select it, but not deselect other items, and a key-modified click will de-select only the items specifically indicated by the user (either individually, or under multiselect). To make things a bit more challenging, we need our treeview to be virtualized, and the RadTreeViewItem's IsSelected property is bound to a "Selected" property of the business objects (each cad entity), following an MVVM design pattern.

    So what I'm having trouble finding out is what methods I need to override on RadTreeView (or even RadTreeViewItem?) to change the selection behavior with the mouse/keyboard, but still allow the the RadTreeView to fire the events it does on selection change (we've found these are still important regardless of our databinding due to ui virtualization).

    Thanks!
  2. Robert
    Robert avatar
    15 posts
    Member since:
    Mar 2013

    Posted 12 Apr 2013 Link to this post

    Ok, I know I'm replying to my own post, but I found a way around my problem, and thought I'd share an example for others to follow. I got some of the idea from this forum post and some others that I don't remember. The basic gist is that I needed to disable unselecting items when a new one was selected (so selection is always added, without a keypress), and change the behavior of the control key so that items are deleted when its pressed. I also had to implement shift-multiselect, and shift-ctrl-multipleunselect similarly. It was also databound to a list of entities (my business objects) and I had to make sure the updates from those still did the selection/unselection and only handle user interface clicking. In the end I put the RadTreeView on a new usercontrol and used event handling, and judicious use of the e.Handled = true setting, to achieve my goals. This is probably not complete, as I'm not handling keyboard-only selection, or stylus events, but for my purposes this is good enough. Here's some sample code:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using Telerik.Windows;
    using Telerik.Windows.Controls;
    using System.Diagnostics;
    using Sample.Entities;
     
    namespace SampleTree
    {
        /// <summary>
        /// Interaction logic for EntityTreeView.xaml
        /// </summary>
        public partial class EntityTreeView : UserControl
        {
     
            private bool bUserInitiated = false;
            private Entity PreviouslyClickedEntity = null;
            private Entity CurrentClickedEntity = null;
     
            public EntityTreeView()
            {
                InitializeComponent();
            }
     
            private void treeView1_MouseUp(object sender, MouseButtonEventArgs e)
            {
                bUserInitiated = false;
            }
     
            private void treeView1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
            {
                bUserInitiated = true;
     
                // Set the previous and current clicked entities
                RadTreeViewItem tvitem = VisualUpwardSearch(e.OriginalSource as DependencyObject);
                PreviouslyClickedEntity = CurrentClickedEntity;
                if (tvitem != null && tvitem.Item != null)
                    CurrentClickedEntity = tvitem.Item as Entity;
                else
                {
                    CurrentClickedEntity = null;
                    bUserInitiated = false;
                }
     
                if (KeyboardModifiers.IsShiftDown == true && PreviouslyClickedEntity != null &&
                    CurrentClickedEntity != null && PreviouslyClickedEntity != CurrentClickedEntity)
                {
                    e.Handled = true;
                    bool SwitchState = false;
     
                    if (KeyboardModifiers.IsControlDown == false)
                    {
                        SwitchState = true;
                    }
     
                    // ... Custom selection/deselection handling happens here ...
                     
                }
            }
     
            private void treeView1_PreviewSelected(object sender, Telerik.Windows.RadRoutedEventArgs e)
            {
                //Don't allow selection if ctrl is pressed
                if (bUserInitiated == true && KeyboardModifiers.IsControlDown == true)
                    e.Handled = true;
            }
     
            private void treeView1_PreviewUnselected(object sender, Telerik.Windows.RadRoutedEventArgs e)
            {
                // only allow unselection if ctrl is pressed
                if (bUserInitiated == true && KeyboardModifiers.IsControlDown == false)
                    e.Handled = true;
            }
     
            static RadTreeViewItem VisualUpwardSearch(DependencyObject source)
            {
                while (source != null && !(source is RadTreeViewItem))
                    source = VisualTreeHelper.GetParent(source);
     
                return source as RadTreeViewItem;
            }
     
        }
    }
  3. UI for WPF is Visual Studio 2017 Ready
Back to Top