56

How is it possible to programmatically select an item in a WPF TreeView? The ItemsControl model seems to prevent it.

akjoshi
  • 14,589
  • 13
  • 94
  • 116
Thomas Bratt
  • 40,822
  • 34
  • 113
  • 133

16 Answers16

41

For those who are still looking for the right solution to this problem here is the one below. I found this one in the comments to the Code Project article “WPF TreeView Selection” http://www.codeproject.com/KB/WPF/TreeView_SelectionWPF.aspx by DaWanderer. It was posted by Kenrae on Nov 25 2008. This worked great for me. Thanks Kenrae!

Here is his post:

Instead of walking the tree, have your own data object have the IsSelected property (and I recommend the IsExpanded property too). Define a style for the TreeViewItems of the tree using the ItemContainerStyle property on the TreeView that binds those properties from the TreeViewItem to your data objects. Something like this:

<Style x:Key="LibraryTreeViewItemStyle"
               TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded"
                        Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected"
                        Value="{Binding IsSelected, Mode=TwoWay}" />
            <Setter Property="FontWeight"
                        Value="Normal" />
            <Style.Triggers>
                  <Trigger Property="IsSelected"
                              Value="True">
                        <Setter Property="FontWeight"
                                    Value="Bold" />
                  </Trigger>
            </Style.Triggers>
      </Style>

<TreeView ItemsSource="{Binding Path=YourCollection}"
               ItemContainerStyle="{StaticResource LibraryTreeViewItemStyle}"
               ItemTemplate={StaticResource YourHierarchicalDataTemplate}/>
SeToY
  • 5,317
  • 10
  • 45
  • 89
kuninl
  • 431
  • 1
  • 4
  • 5
  • It works! `ItemContainerStyle="{StaticResource LibraryTreeViewItemStyle}"` – Eric Chai May 29 '12 at 07:23
  • 4
    Doesn't work for me; the programmatical selection is always automatically reset to what was selected before, unless nothing was selected before. I've created a [related question](http://stackoverflow.com/questions/13778515/synchronizing-a-selectedpath-property-with-the-selecteditem-in-wpfs-treeview) with sample code. – O. R. Mapper Dec 09 '12 at 13:23
  • Doesn't work for me; only the 1st item that I set IsExpanded = true on gets expanded, all the other items i try to expand don't expand and nothing is ever getting selected. – Nick Oct 18 '13 at 13:23
  • 1
    Nevermind. I was using an IEnumerable for my collection, I changed it to an ObservableCollection and now it works. – Nick Oct 18 '13 at 13:51
  • Not only is placing IsSelected on a model class rather than on a class that manages it, a bad design decision, it also does not address the case say if the object is being displayed in multiple trees – MickyD Nov 19 '13 at 02:57
  • 2
    This does not always work. TreeView.SelectedItem retains old value, which causes bizarre bugs in some cases (multiselect scenario). – Pavel Tupitsyn Apr 17 '14 at 16:27
  • I've been working on this for like 6 hours...I've tried every freakin post on the subject here on SO (and other places)...this is the only thing that works. If anybody else is strugging with this...and you have data models in your treeview that don't have the "IsSelected" property on them, and you don't want to change them...JUST DO IT. Being able to map to this property 2-way solves so many problems. – barbrady Feb 17 '17 at 00:10
  • 4
    Works great, with some extra notes: the model needs to implement INotifyPropertyChanged and fire the PropertyChangedEvent for the IsSelected and IsExpanded properties. Also, if you want to expand an item, you need to expand all of its ancestors as well, which means that it makes sense for the model to also have a Parent relationship. – Nikolaos Georgiou Sep 19 '17 at 19:26
  • This works for me but I want to trigger this when I click a button inside the treeview instead. – Rob Jul 19 '18 at 18:46
  • If you're using the MVVM pattern then this might not be a poor solution because MVVM encourages you to put UI based data in the view model. However, UI data should not be added to the view model unnecessarily. This code encourages you to hack around the TreeView control's deficiency by polluting the view model further than is necessary. It will bloat every view model that you intend on using. – Christian Findlay Nov 19 '18 at 00:42
  • DOesn't this require unsetting the IsSelected and IsExpanded properties whenever the user selects or expands soemthing in the tree? – Stealth Rabbi Jan 09 '19 at 15:09
29

It's a real pain for some strange reason, you have to use ContainerFromItem to get the container, then invoke the select method.

//  selectedItemObject is not a TreeViewItem, but an item from the collection that 
//  populated the TreeView.

var tvi = treeView.ItemContainerGenerator.ContainerFromItem(selectedItemObject) 
          as TreeViewItem;

if (tvi != null)
{
    tvi.IsSelected = true;
}

There once was a blog entry on how to do it here, but the link is dead now.

Steven Robbins
  • 25,817
  • 7
  • 71
  • 89
23

You need to get the TreeViewItem and then set IsSelected to true.

Tim Cooper
  • 144,163
  • 35
  • 302
  • 261
Kent Boogaart
  • 165,446
  • 34
  • 376
  • 376
10

I've succeeded with this code:

public static TreeViewItem FindTviFromObjectRecursive(ItemsControl ic, object o) {
  //Search for the object model in first level children (recursively)
  TreeViewItem tvi = ic.ItemContainerGenerator.ContainerFromItem(o) as TreeViewItem;
  if (tvi != null) return tvi;
  //Loop through user object models
  foreach (object i in ic.Items) {
    //Get the TreeViewItem associated with the iterated object model
    TreeViewItem tvi2 = ic.ItemContainerGenerator.ContainerFromItem(i) as TreeViewItem;
    tvi = FindTviFromObjectRecursive(tvi2, o);
    if (tvi != null) return tvi;
  }
  return null;
}

Usage:

var tvi = FindTviFromObjectRecursive(TheTreeView, TheModel);
if (tvi != null) tvi.IsSelected = true;
Fandi Susanto
  • 1,754
  • 22
  • 22
  • 3
    This should be the accepted answer. This code also finds and selected child elements. – uceumern Oct 19 '18 at 06:57
  • This worked for me after I added a null check: if (tvi2 != null) that surrounds the recursive call to FindTviFromObjectRecursive and the following line that returns tvi. I'm not sure how this works without that check because it will otherwise try to continue on leafs... – Allen Pestaluky May 06 '20 at 21:02
5

This is not as simple as it looks, the link provided by Steven has a solution posted in 2008, which may still works but doesn't take care of Virtualized TreeViews. Moreover many other problems are mentioned in comments of that article. No offences, but I am also stuck with same problem and can't find a perfect solution. Here are the links to some of the articles/posts which helped me a lot-

How can I expand items in a TreeView? – Part III: http://bea.stollnitz.com/blog/?p=59

Programmatically Selecting an Item in a TreeView: http://blog.quantumbitdesigns.com/2008/07/22/programmatically-selecting-an-item-in-a-treeview/#respond

TreeView, TreeViewItem and IsSelected: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7e368b93-f509-4cd6-88e7-561e8d3246ae/

akjoshi
  • 14,589
  • 13
  • 94
  • 116
  • Look at this post for issues with implementing selection with Virtualization and Load-on-demand - http://stackoverflow.com/questions/3715583/need-a-sample-for-wpf-treeview-search-with-virtualization-and-load-on-demand – akjoshi Jan 12 '11 at 10:04
  • MSDN Document "How to: Find a TreeViewItem in a TreeView" refers to virtualized TreeViews as well. http://msdn.microsoft.com/en-us/library/ff407130.aspx#Y486 – Omer Raviv Feb 27 '11 at 12:49
  • 2
    I find your second link (quantumbdesigns) the right solution, because it allows you to select a node in the TreeView from the representative MVVM instance. – JoanComasFdz Apr 13 '12 at 08:53
3

I wrote an extension method:

using System.Windows.Controls;

namespace Extensions
{
    public static class TreeViewEx
    {
        /// <summary>
        /// Select specified item in a TreeView
        /// </summary>
        public static void SelectItem(this TreeView treeView, object item)
        {
            var tvItem = treeView.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
            if (tvItem != null)
            {
                tvItem.IsSelected = true;
            }
        }
    }
}

Which I can use like this:

if (_items.Count > 0)
    _treeView.SelectItem(_items[0]);
Kristopher Johnson
  • 76,675
  • 54
  • 235
  • 299
1

If you want to select item located withing children of child you can user recursion to do that.

public bool Select(TreeViewItem item, object select) // recursive function to set item selection in treeview
{
    if (item == null)
        return false;
    TreeViewItem child = item.ItemContainerGenerator.ContainerFromItem(select) as TreeViewItem;
    if (child != null)
    {
        child.IsSelected = true;
        return true;
    }
    foreach (object c in item.Items)
    {
        bool result = Select(item.ItemContainerGenerator.ContainerFromItem(c) as TreeViewItem, select);
        if (result == true)
            return true;
    }
    return false;
}
nhahtdh
  • 52,949
  • 15
  • 113
  • 149
purvin
  • 11
  • 1
0

Just thought I would chime in with the solution I went with, in case this can help anyone. Note that the best way to do this is using a bound property like 'IsSelected' as per kuninl's answer, but in my case it was a legacy application that did not follow MVVM, so I ended up with the below.

private void ChangeSessionSelection()
{
    foreach (SessionContainer item in this.treeActiveSessions.Items)
    {
        var treeviewItem = this.treeActiveSessions.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;

        if (item.Session == this.selectedSession.Session)
        {
            treeviewItem.IsSelected = true;
            treeviewItem.IsExpanded = true;
        }
        else
        {
            treeviewItem.IsSelected = false;
            treeviewItem.IsExpanded = false;
        }
    }            
}

What this does is select and expand the treeview item in the UI that represents the selected dataitem in the code behind. The purpose of this was to have the selection change in the treeview when the users selection changed in an items control in the same window.

RobJohnson
  • 845
  • 11
  • 18
0

I have created a method VisualTreeExt.GetDescendants<T> that returns an enumerable collection of elements that match the specified type:

public static class VisualTreeExt
{
  public static IEnumerable<T> GetDescendants<T>(DependencyObject parent) where T : DependencyObject
  {
    var count = VisualTreeHelper.GetChildrenCount(parent);
    for (var i = 0; i < count; ++i)
    {
       // Obtain the child
       var child = VisualTreeHelper.GetChild(parent, i);
       if (child is T)
         yield return (T)child;

       // Return all the descendant children
       foreach (var subItem in GetDescendants<T>(child))
         yield return subItem;
    }
  }
}

When you ask for VisualTreeHelperExt.GetDescendants<TreeViewItem>(MyAmazingTreeView) you'll get all the TreeViewItem childs. You can select a particular value using the following piece of code:

var treeViewItem = VisualTreeExt.GetDescendants<TreeViewItem>(MyTreeView).FirstOrDefault(tvi => tvi.DataContext == newValue);
if (treeViewItem != null)
  treeViewItem.IsSelected = true;

It's a bit of a dirty solution (and probably not the most efficient) and won't work if you're using a virtualized TreeView, because it depends on the existance of the actual visual elements. But it works for my situation...

Ramon de Klein
  • 4,178
  • 1
  • 33
  • 45
0

Yeah.. I know many years past since the question was asked but.. still no quick solution to this problem.. and So:

The following will do what the OP asked for.

What I basically done is reading all the answers in this page and following all the relevant links to create a once and for all solution to this irritating problem.

Benefits:

  • It support Virtualizing TreeView as well.
  • It using the behavior technique, so XAML is way easy.
  • Adds a dependancy-property to allow binding to the selected TreeView Item.

This part is the only code you need to copy, the other parts are just to help complete an example.

public static class TreeViewSelectedItemExBehavior
{
    private static List<TreeView> isRegisteredToSelectionChanged = new List<TreeView>();

    public static readonly DependencyProperty SelectedItemExProperty =
        DependencyProperty.RegisterAttached("SelectedItemEx",
            typeof(object),
            typeof(TreeViewSelectedItemExBehavior),
            new FrameworkPropertyMetadata(new object(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemExChanged, null));

    #region SelectedItemEx

    public static object GetSelectedItemEx(TreeView target)
    {
        return target.GetValue(SelectedItemExProperty);
    }

    public static void SetSelectedItemEx(TreeView target, object value)
    {
        target.SetValue(SelectedItemExProperty, value);
        var treeViewItemToSelect = GetTreeViewItem(target, value);
        if (treeViewItemToSelect == null)
        {
            if (target.SelectedItem == null)
                return;
            var treeViewItemToUnSelect = GetTreeViewItem(target, target.SelectedItem);
            treeViewItemToUnSelect.IsSelected = false;
        }
        else
            treeViewItemToSelect.IsSelected = true;
    }

    public static void OnSelectedItemExChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        var treeView = depObj as TreeView;
        if (treeView == null)
            return;
        if (!isRegisteredToSelectionChanged.Contains(treeView))
        {
            treeView.SelectedItemChanged += TreeView_SelectedItemChanged;
            isRegisteredToSelectionChanged.Add(treeView);
        }
    }
    
    #endregion

    private static void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        var treeView = (TreeView)sender;
        SetSelectedItemEx(treeView, e.NewValue);
    }

    #region Helper Structures & Methods

    public class MyVirtualizingStackPanel : VirtualizingStackPanel
    {
        /// <summary>
        /// Publically expose BringIndexIntoView.
        /// </summary>
        public void BringIntoView(int index)
        {
            BringIndexIntoView(index);
        }
    }

    /// <summary>Recursively search for an item in this subtree.</summary>
    /// <param name="container">The parent ItemsControl. This can be a TreeView or a TreeViewItem.</param>
    /// <param name="item">The item to search for.</param>
    /// <returns>The TreeViewItem that contains the specified item.</returns>
    private static TreeViewItem GetTreeViewItem(ItemsControl container, object item)
    {
        if (container != null)
        {
            if (container.DataContext == item)
            {
                return container as TreeViewItem;
            }

            // Expand the current container
            if (container is TreeViewItem && !((TreeViewItem)container).IsExpanded)
            {
                container.SetValue(TreeViewItem.IsExpandedProperty, true);
            }

            // Try to generate the ItemsPresenter and the ItemsPanel.
            // by calling ApplyTemplate.  Note that in the 
            // virtualizing case even if the item is marked 
            // expanded we still need to do this step in order to 
            // regenerate the visuals because they may have been virtualized away.

            container.ApplyTemplate();
            ItemsPresenter itemsPresenter =
                (ItemsPresenter)container.Template.FindName("ItemsHost", container);
            if (itemsPresenter != null)
            {
                itemsPresenter.ApplyTemplate();
            }
            else
            {
                // The Tree template has not named the ItemsPresenter, 
                // so walk the descendents and find the child.
                itemsPresenter = FindVisualChild<ItemsPresenter>(container);
                if (itemsPresenter == null)
                {
                    container.UpdateLayout();

                    itemsPresenter = FindVisualChild<ItemsPresenter>(container);
                }
            }

            Panel itemsHostPanel = (Panel)VisualTreeHelper.GetChild(itemsPresenter, 0);


            // Ensure that the generator for this panel has been created.
            UIElementCollection children = itemsHostPanel.Children;

            MyVirtualizingStackPanel virtualizingPanel =
                itemsHostPanel as MyVirtualizingStackPanel;

            for (int i = 0, count = container.Items.Count; i < count; i++)
            {
                TreeViewItem subContainer;
                if (virtualizingPanel != null)
                {
                    // Bring the item into view so 
                    // that the container will be generated.
                    virtualizingPanel.BringIntoView(i);

                    subContainer =
                        (TreeViewItem)container.ItemContainerGenerator.
                        ContainerFromIndex(i);
                }
                else
                {
                    subContainer =
                        (TreeViewItem)container.ItemContainerGenerator.
                        ContainerFromIndex(i);

                    // Bring the item into view to maintain the 
                    // same behavior as with a virtualizing panel.
                    subContainer.BringIntoView();
                }

                if (subContainer != null)
                {
                    // Search the next level for the object.
                    TreeViewItem resultContainer = GetTreeViewItem(subContainer, item);
                    if (resultContainer != null)
                    {
                        return resultContainer;
                    }
                    else
                    {
                        // The object is not under this TreeViewItem
                        // so collapse it.
                        subContainer.IsExpanded = false;
                    }
                }
            }
        }

        return null;
    }

    /// <summary>Search for an element of a certain type in the visual tree.</summary>
    /// <typeparam name="T">The type of element to find.</typeparam>
    /// <param name="visual">The parent element.</param>
    /// <returns></returns>
    private static T FindVisualChild<T>(Visual visual) where T : Visual
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
        {
            Visual child = (Visual)VisualTreeHelper.GetChild(visual, i);
            if (child != null)
            {
                T correctlyTyped = child as T;
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                }

                T descendent = FindVisualChild<T>(child);
                if (descendent != null)
                {
                    return descendent;
                }
            }
        }
        return null;
    }
    
    #endregion
}

And this is an example of how the TreeView line looks like in XAML:

<TreeView x:Name="trvwSs"
    Grid.Column="2" Grid.Row="1" Margin="4" ItemsSource="{Binding ItemsTreeViewSs}"
    behaviors:TreeViewSelectedItemExBehavior.SelectedItemEx="{Binding SelectedItemTreeViewSs}" />

Only thing to worry about is to make sure your view-model property that you about to bound to SelectedItemEx is not null. But that is not a special case.. Just mentioned it in case people get confused.

public class VmMainContainer : INotifyPropertyChanged
{
    private object selectedItemTreeViewSs = new object();
    private ObservableCollection<object> selectedItemsTreeViewSs = new ObservableCollection<object>();
    private ObservableCollection<VmItem> itemsTreeViewSs = new ObservableCollection<VmItem>();

    public object SelectedItemTreeViewSs
    {
        get
        {
            return selectedItemTreeViewSs;
        }
        set
        {
            selectedItemTreeViewSs = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItemTreeViewSs)));
        }
    }

    public ObservableCollection<object> SelectedItemsTreeViewSs
    {
        get
        {
            return selectedItemsTreeViewSs;
        }
        set
        {
            selectedItemsTreeViewSs = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItemsTreeViewSs)));
        }
    }

    public ObservableCollection<VmItem> ItemsTreeViewSs
    {
        get { return itemsTreeViewSs; }
        set
        {
            itemsTreeViewSs = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemsTreeViewSs)));
        }
    }
}

And last thing.. example of selecting programmatically: I created a button on my MainWindow.xaml and from its handler..

private void Button_Click(object sender, RoutedEventArgs e)
{
    TreeViewSelectedItemExBehavior.SetSelectedItemEx(trvwSs, trvwSs.Items[3]);
    //TreeViewSelectedItemExBehavior.SetSelectedItemEx(trvwSs, null);
}

Hope this helps someone :)

Mark A. Donohoe
  • 23,825
  • 17
  • 116
  • 235
G.Y
  • 5,341
  • 2
  • 30
  • 51
  • 1
    It looks like a working solution. What I don't like about it is that it's global. This will lead to memory leaks because it stores all `TreeView`s around. Besides you never unregister from the events you subscribe to. If the elements gets removes, references will still remain to them from your behavior. Some nice work to take out stuff from, but is leaky as a whole. – Shimmy Weitzhandler Nov 22 '17 at 05:30
0

You can do it via code behind like

if (TreeView1.Items.Count > 0)
        (TreeView1.Items[0] as TreeViewItem).IsSelected = true;
DmitryBoyko
  • 32,983
  • 69
  • 281
  • 458
0

The proposed answer doesn't work. @fandisusanto's answer probably does work, but it can be made simpler. This is the simplest answer I can come up with:

    private static void DeselectTreeViewItem(IEnumerable<TreeViewItem> treeViewItems)
    {
        foreach (var treeViewItem in treeViewItems)
        {
            if (treeViewItem.IsSelected)
            {
                treeViewItem.IsSelected = false;
                return;
            }

            DeselectTreeViewItem(treeViewItem.Items.Cast<TreeViewItem>());
        }
    }

Usage:

    private void ClearSelectedItem()
    {
        if (AssetTreeView.SelectedItem != null)
        {
            DeselectTreeViewItem(AssetTreeView.Items.Cast<TreeViewItem>());
        }
    }
Christian Findlay
  • 4,791
  • 1
  • 33
  • 74
0

This is my solution. The others failed for me in various ways. You need to walk the tree from top to bottom, looking for the tree item at each level, expanding and updating the layout along the way.

This function takes a stack of nodes where the first one out of the stack is the top most node, and each subsequent node on the stack is a child of the previous parent. The second argument is the TreeView.

As each item is found, that item is expanded, and the final item is returned, where the caller can select it.

    TreeViewItem FindTreeViewItem( Stack<object> nodeStack, TreeView treeView )
    {
        ItemsControl itemsControl = treeView;

        while (nodeStack.Count > 0) {
            object node = nodeStack.Pop();
            bool found = false;

            foreach (object item in itemsControl.Items) {
                if (item == node) {
                    found = true;

                    if (itemsControl.ItemContainerGenerator.ContainerFromItem( item ) is TreeViewItem treeViewItem) {
                        if (nodeStack.Count == 0) {
                            return treeViewItem;
                        }

                        itemsControl = treeViewItem;
                        treeViewItem.IsExpanded = true;
                        treeViewItem.UpdateLayout();
                        break;
                    }
                }
            }

            if (!found) {
                return null;
            }
        }

        return null;
    }

Example of how to call it:

    // Build nodeStack here from your data

    TreeViewItem treeViewItem = FindTreeViewItem( nodeStack, treeView );

    if (treeViewItem != null) {
        treeViewItem.IsSelected = true;
        treeViewItem.BringIntoView();
    }
Eric Vasilik
  • 342
  • 2
  • 13
0

Try with this

    /// <summary>
    /// Selects the tree view item.
    /// </summary>
    /// <param name="Collection">The collection.</param>
    /// <param name="Value">The value.</param>
    /// <returns></returns>
    private TreeViewItem SelectTreeViewItem(ItemCollection Collection, String Value)
    {
        if (Collection == null) return null;
        foreach(TreeViewItem Item in Collection)
        {
            /// Find in current
            if (Item.Header.Equals(Value))
            {
                Item.IsSelected = true;
                return Item;
            }
            /// Find in Childs
            if (Item.Items != null)
            {
                TreeViewItem childItem = this.SelectTreeViewItem(Item.Items, Value);
                if (childItem != null)
                {
                    Item.IsExpanded = true;
                    return childItem;
                }
            }
        }
        return null;
    }

Reference: http://amastaneh.blogspot.com/2011/06/wpf-selectedvalue-for-treeview.html

Amir Astaneh
  • 1,856
  • 16
  • 18
  • 1
    This does only work if the itemcollections entries are "TreeViewItem"s - if one works with a data binding, the content of "Items" are the type of the data bindings entries. – lunatix Oct 29 '12 at 15:46
0

I wrote a Helper class for this, which supports MVVM and lazy loaded items.

public class TreeViewHelper<TModel>
{
    public TreeViewHelper(TreeView treeView, Func<TModel, TModel> getParent, Func<TModel, IList<TModel>> getSubItems)
    {
        TreeView = treeView;
        GetParent = getParent;
        GetSubItems = getSubItems;
    }

    public TreeView TreeView { get; }
    public Func<TModel, TModel> GetParent { get; }
    public Func<TModel, IList<TModel>> GetSubItems { get; }

    public void SelectItemWhileLoaded(TModel node, IList<TModel> rootNodes)
    {
        if (TreeView.IsLoaded)
        {
            SelectItem(node, rootNodes);
        }
        else
        {
            TreeView.Loaded += TreeView_Loaded;
            void TreeView_Loaded(object sender, System.Windows.RoutedEventArgs e)
            {
                TreeView.Loaded -= TreeView_Loaded;
                SelectItem(node, rootNodes);
            }
        }
    }


    public void SelectItem(TModel node, IList<TModel> rootNodes)
    {
        Stack<TModel> nodes = new Stack<TModel>();
        //push into stack
        while (!rootNodes.Contains(node))
        {
            nodes.Push(node);
            node = GetParent(node);
        }
        TreeViewItem treeViewItem = TreeView.ItemContainerGenerator
            .ContainerFromItem(node) as TreeViewItem;
        if (nodes.Count == 0)
        {
            //Top level
            treeViewItem.IsSelected = true;
            treeViewItem.BringIntoView();
            return;
        }
        Expanded(true);
        void Expanded(bool top)
        {
            if (!top)
            {
                treeViewItem = treeViewItem.ItemContainerGenerator
                    .ContainerFromItem(node) as TreeViewItem;
                if (nodes.Count == 0)
                {
                    treeViewItem.IsSelected = true;
                    treeViewItem.BringIntoView();
                    return;
                }
            }
            node = nodes.Pop();
            treeViewItem.IsExpanded = true;
            if (treeViewItem.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
            {
                Expanded(true);
            }
            else
            {
                //Lazy
                treeViewItem.ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged;
            }
        }
        void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
        {
            if (treeViewItem.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
            {
                treeViewItem.ItemContainerGenerator.StatusChanged -= ItemContainerGenerator_StatusChanged;
                Expanded(false);
            }
        }
    }
}
autodotua
  • 1
  • 2
-1

I think this is the simplest solution:

private void MouseDownEventProcessing(TreeNodeMouseClickEventArgs e)
{
    tvEmployeeDirectory.SelectedNode = e.Node;
}
Indian
  • 509
  • 11
  • 24