Data binding to SelectedItem in a WPF Treeview

后端 未结 20 811
南方客
南方客 2020-11-22 05:39

How can I retrieve the item that is selected in a WPF-treeview? I want to do this in XAML, because I want to bind it.

You might think that it is SelectedItem

20条回答
  •  失恋的感觉
    2020-11-22 06:34

    I bring you my solution which offers the following features:

    • Supports 2 ways binding

    • Auto updates the TreeViewItem.IsSelected properties (according to the SelectedItem)

    • No TreeView subclassing

    • Items bound to ViewModel can be of any type (even null)

    1/ Paste the following code in your CS:

    public class BindableSelectedItem
    {
        public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.RegisterAttached(
            "SelectedItem", typeof(object), typeof(BindableSelectedItem), new PropertyMetadata(default(object), OnSelectedItemPropertyChangedCallback));
    
        private static void OnSelectedItemPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var treeView = d as TreeView;
            if (treeView != null)
            {
                BrowseTreeViewItems(treeView, tvi =>
                {
                    tvi.IsSelected = tvi.DataContext == e.NewValue;
                });
            }
            else
            {
                throw new Exception("Attached property supports only TreeView");
            }
        }
    
        public static void SetSelectedItem(DependencyObject element, object value)
        {
            element.SetValue(SelectedItemProperty, value);
        }
    
        public static object GetSelectedItem(DependencyObject element)
        {
            return element.GetValue(SelectedItemProperty);
        }
    
        public static void BrowseTreeViewItems(TreeView treeView, Action onBrowsedTreeViewItem)
        {
            var collectionsToVisit = new System.Collections.Generic.List> { new Tuple(treeView.ItemContainerGenerator, treeView.Items) };
            var collectionIndex = 0;
            while (collectionIndex < collectionsToVisit.Count)
            {
                var itemContainerGenerator = collectionsToVisit[collectionIndex].Item1;
                var itemCollection = collectionsToVisit[collectionIndex].Item2;
                for (var i = 0; i < itemCollection.Count; i++)
                {
                    var tvi = itemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                    if (tvi == null)
                    {
                        continue;
                    }
    
                    if (tvi.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
                    {
                        collectionsToVisit.Add(new Tuple(tvi.ItemContainerGenerator, tvi.Items));
                    }
    
                    onBrowsedTreeViewItem(tvi);
                }
    
                collectionIndex++;
            }
        }
    
    }
    

    2/ Example of use in your XAML file

      
    

提交回复
热议问题