SoFunction
Updated on 2025-03-08

Usage of TreeView control in WPF

The use of TreeView in WPF is very different from that in WinForm. Common operations such as expanding a node, obtaining a parent node, and determining whether a node is selected have related functions in WinForm, but they cannot be easily implemented in WPF.

A conventional way is to bidirectionally bind the IsSelect, IsExpanded and other properties in the TreeViewItem node to the node data to be displayed through the MVVM mode, and then directly implement related operations through the attributes of the node data.

However, sometimes, what should we do when we don’t have a ViewModel layer but want to get or set these properties directly and simply like WinFrom. In fact, WPF still provides settings similar to those in WinForm, but the form is different, but it is not as intuitive and convenient as WinFrom. Someone on CodeProject summarized the commonly used functions and wrote them into extension functions, which mainly provide the following functions:

public static void SelectObject(this TreeView treeView, object obj)
public static void SelectObject(this TreeView treeView, object obj, bool selected)
public static bool IsObjectSelected(this TreeView treeView, object obj)
public static bool IsObjectFocused(this TreeView treeView, object obj)
public static void ExpandObject(this TreeView treeView, object obj)
public static void ExpandObject(this TreeView treeView, object obj, bool expanded)
public static bool IsObjectExpanded(this TreeView treeView, object obj)
public static TreeViewItem GetParentItem(this TreeViewItem item)

The article address is as follows:WPF TreeView tools

However, there is a small bug here: when delay binding is used in the TreeView node, obtaining TreeItem according to the data node will fail. I have corrected it here. Interested friends can directly use my modified function.

    public static class TreeViewTools
    {
        /// <summary>
        /// Returns the TreeViewItem of a data bound object.
        /// </summary>
        /// <param name="treeView">TreeView</param>
        /// <param name="obj">Data bound object</param>
        /// <returns>The TreeViewItem of the data bound object or null.</returns>
        public static TreeViewItem GetItemFromObject(this TreeView treeView, object obj)
        {
            try
            {
                DependencyObject dObject = GetContainerFormObject(treeView, obj);
                TreeViewItem tvi = dObject as TreeViewItem;
                while (tvi == null)
                {
                    dObject = (dObject);
                    tvi = dObject as TreeViewItem;
                }
                return tvi;
            }
            catch { }
            return null;
        }

        private static DependencyObject GetContainerFormObject(ItemsControl item, object obj)
        {
            if (item == null)
                return null;

            DependencyObject dObject = null;
            dObject = (obj);

            if (dObject != null)
                return dObject;

            var query = from childItem in <object>()
                        let childControl = (childItem) as ItemsControl
                        select GetContainerFormObject(childControl, obj);

            return (i => i != null);
        }

        /// <summary>
        /// Selects a data bound object of a TreeView.
        /// </summary>
        /// <param name="treeView">TreeView</param>
        /// <param name="obj">Data bound object</param>
        public static void SelectObject(this TreeView treeView, object obj)
        {
            (obj, true);
        }

        /// <summary>
        /// Selects or deselects a data bound object of a TreeView.
        /// </summary>
        /// <param name="treeView">TreeView</param>
        /// <param name="obj">Data bound object</param>
        /// <param name="selected">select or deselect</param>
        public static void SelectObject(this TreeView treeView, object obj, bool selected)
        {
            var tvi = (obj);
            if (tvi != null)
            {
                 = selected;
            }
        }

        /// <summary>
        /// Returns if a data bound object of a TreeView is selected.
        /// </summary>
        /// <param name="treeView">TreeView</param>
        /// <param name="obj">Data bound object</param>
        /// <returns>Returns true if the object is selected, and false if it is not selected or obj is not in the tree.</returns>
        public static bool IsObjectSelected(this TreeView treeView, object obj)
        {
            var tvi = (obj);
            if (tvi != null)
            {
                return ;
            }
            return false;
        }

        /// <summary>
        /// Returns if a data bound object of a TreeView is focused.
        /// </summary>
        /// <param name="treeView">TreeView</param>
        /// <param name="obj">Data bound object</param>
        /// <returns>Returns true if the object is focused, and false if it is not focused or obj is not in the tree.</returns>
        public static bool IsObjectFocused(this TreeView treeView, object obj)
        {
            var tvi = (obj);
            if (tvi != null)
            {
                return ;
            }
            return false;
        }

        /// <summary>
        /// Expands a data bound object of a TreeView.
        /// </summary>
        /// <param name="treeView">TreeView</param>
        /// <param name="obj">Data bound object</param>
        public static void ExpandObject(this TreeView treeView, object obj)
        {
            (obj, true);
        }

        /// <summary>
        /// Expands or collapses a data bound object of a TreeView.
        /// </summary>
        /// <param name="treeView">TreeView</param>
        /// <param name="obj">Data bound object</param>
        /// <param name="expanded">expand or collapse</param>
        public static void ExpandObject(this TreeView treeView, object obj, bool expanded)
        {
            var tvi = (obj);
            if (tvi != null)
            {
                 = expanded;
                if (expanded)
                {
                    // update layout, so that following calls to . SelectObject on child nodes will 
                    // find theire TreeViewNodes
                    ();
                }
            }
        }

        /// <summary>
        /// Returns if a douta bound object of a TreeView is expanded.
        /// </summary>
        /// <param name="treeView">TreeView</param>
        /// <param name="obj">Data bound object</param>
        /// <returns>Returns true if the object is expanded, and false if it is collapsed or obj is not in the tree.</returns>
        public static bool IsObjectExpanded(this TreeView treeView, object obj)
        {
            var tvi = (obj);
            if (tvi != null)
            {
                return ;
            }
            return false;
        }

        /// <summary>
        /// Retuns the parent TreeViewItem.
        /// </summary>
        /// <param name="item">TreeViewItem</param>
        /// <returns>Parent TreeViewItem</returns>
        public static TreeViewItem GetParentItem(this TreeViewItem item)
        {
            var dObject = (item);
            TreeViewItem tvi = dObject as TreeViewItem;
            while (tvi == null)
            {
                dObject = (dObject);
                tvi = dObject as TreeViewItem;
            }
            return tvi;
        }
    }

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.