Click here to Skip to main content
Click here to Skip to main content

WPF MultiSelect TreeView Sample

, 23 Mar 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
Shows how to add multi-select capabilities to WPF TreeView control
MultiSelectTreeView

Introduction

WPF TreeView control does not give developers an ability to multi-select the nodes of the tree. This article shows a very simple example that simulates multi-select capability for a WPF TreeView control. I say "simulate" because it discards the WPF select mechanism and replaces it with its own.

Ideally another user control called, say MultiSelectTreeView, should be created and packed in a separate DLL, but since I do not have much time to spend on it, I simply showed how to do it by modifying the code in the main Window class.

To multi-select, you should use the left ctrl key on your keyboard together with the mouse. The shift key and ctrl-A multi-select functions were not added (again for the lack of time), but can be added in exactly the same manner.

Simulating the Multi-Selection

As stated above, we disable the WPF selection and, instead use our own selection mechanism, according to which, all TreeViewItem elements that have been selected are stored in selectedItems set. The set is simulated by a Dictionary with null values.

The selected items change their Background and Foreground properties to Brushes.Black and Brushes.White correspondingly.

If LeftCtrl key is not pressed, then, before selecting an item, we clean all the previous selections. If LeftCtrl key is pressed, the previous selections are not cleaned.

Using the Code

The top level code is located in MyTreeView_SelectedItemChanged function and called when SelectedItemChanged event is fired on the TreeView.

First, prevent WPF selection:

treeViewItem.IsSelected = false;

Then, if LeftCtrl is not pressed, clear the previous selections:

if (!CtrlPressed)
{
    List<treeviewitem /> selectedTreeViewItemList = new List<treeviewitem />();
    foreach (TreeViewItem treeViewItem1 in selectedItems.Keys)
    {
        selectedTreeViewItemList.Add(treeViewItem1);
    }

    foreach (TreeViewItem treeViewItem1 in selectedTreeViewItemList)
    {
        Deselect(treeViewItem1);
    }
}

Then, flip flop the selection state of the item: if selected, make it unselected and vice versa:

ChangeSelectedState(treeViewItem);

We check whether LeftCtrl key is pressed or not by implementing the following property:

bool CtrlPressed
{
   get
   {
       return System.Windows.Input.Keyboard.IsKeyDown(Key.LeftCtrl);
   }
}

History

  • 23rd March, 2008: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nick Polyak
Architect AWebPros
United States United States
I have 15 years of experience developing enterprise software, starting from C++ and Java on UNIX and moving towards C# on Windows platforms.
I am fascinated by the new .NET technologies especially WPF, Silverlight and LINQ.
Recently I decided to make a move and start my own contracting consulting and mentoring company AWebPros.
I can be contacted via my web site awebpros.com or through my blog at nickssoftwareblog.com

Comments and Discussions

 
GeneralMy vote of 3 PinmemberChougule Vinay10-May-12 4:56 
SuggestionSimpler and Improved Version Pinmemberkessbest13-Jul-11 6:04 
GeneralRe: Simpler and Improved Version PinmemberNick Polyak13-Jul-11 13:40 
GeneralRe: Simpler and Improved Version PinmemberPSchegolevatykh28-Mar-12 23:15 
GeneralMake MS notice PinmemberMember 778244829-Mar-11 21:08 
Generaldecent article PinmemberCIDev6-Jan-11 8:22 
QuestionHow to bind the data from database to treeview PinmemberMember 603819613-May-09 18:51 
AnswerRe: How to bind the data from database to treeview PinmemberNick Polyak14-May-09 2:14 
GeneralA good starting point. but ... Pinmembertabor2530-Apr-08 2:18 
GeneralRe: A good starting point. but ... [modified] PinmemberNick Polyak30-Apr-08 2:48 
GeneralRe: A good starting point. but ... Pinmembertabor251-May-08 6:16 
GeneralRe: A good starting point. but ... PinmemberNick Polyak1-May-08 15:12 
GeneralRe: A good starting point. but ... Pinmemberotbld_simon9-Aug-09 21:21 
GeneralRe: A good starting point. but ... PinmemberNick Polyak10-Aug-09 5:09 
AnswerRe: A good starting point. but ... Pinmemberjan.mudrak@gmail.com6-Dec-11 1:02 
Hi,
Nick Polyak is right but, since LeftMouseButton down is not propagated when TreeViewItem is selected, you have to use PreviewMouseDown event:
  <TreeView x:Name="MyTreeView">
    <TreeView.ItemContainerStyle>
      <Style TargetType="{x:Type TreeViewItem}">
        <EventSetter Event="PreviewMouseDown" Handler="SelectionChange" />
      </Style>
    </TreeView.ItemContainerStyle>
  </TreeView>
 
and implement SelectionChange handler with similar manner as MyTreeView_SelectedItemChanged. Unfortunately you will also have to lookup selected item. Final code could look like this:
 
        private void SelectionChange(object sender, MouseButtonEventArgs e)
        {
            if (sender is TreeViewItem)
            {
                TreeViewItem treeviewItem = sender as TreeViewItem;
                treeviewItem = findSelected(treeviewItem);
                
                if (!CtrlPressed)
                {
                    List<TreeViewItem> selectedTreeViewItemList = new List<TreeViewItem>();
                    foreach (TreeViewItem treeViewItem1 in selectedItems.Keys)
                    {
                        selectedTreeViewItemList.Add(treeViewItem1);
                    }
 
                    foreach (TreeViewItem treeViewItem1 in selectedTreeViewItemList)
                    {
                        Deselect(treeViewItem1);
                    }
                }
                ChangeSelectedState(treeviewItem);
            }
            e.Handled = true;
        }
 
        private TreeViewItem findSelected(TreeViewItem root)
        {
            if (!root.IsMouseOver)
            {
                return null;
            }
            else
            {
                for (int i = 0; i < root.Items.Count; i++)
                {
                    if (root.Items[i] is TreeViewItem)
                    {
                        TreeViewItem child = root.Items[i] as TreeViewItem;
                        if (child.IsMouseOver)
                        {
                            return findSelected(child);
                        }
                    }
                }
            }
            return root;
        }
Jan Mudrak

GeneralRe: A good starting point. but ... PinmemberNick Polyak6-Dec-11 15:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.141022.2 | Last Updated 23 Mar 2008
Article Copyright 2008 by Nick Polyak
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid