【问题标题】:Get TreeViewItem for TreeView logical element获取 TreeView 逻辑元素的 TreeViewItem
【发布时间】:2014-07-21 07:14:44
【问题描述】:

我的树视图看起来像这样

<TreeView x:Name="ArticlesTreeView" Grid.Column="0" AllowDrop="True">
            <TreeView.Resources>
                <HierarchicalDataTemplate   DataType="{x:Type structure:NewsPaperDocument}" ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}" Tag="{Binding Object}" FontWeight="Bold" />
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type structure:NewsPaperPage}" ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}" Tag="{Binding Object}" Foreground="#00a300" />
                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type structure:NewsPaperTitle}" ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Name}" Tag="{Binding Object}" Foreground="#da532c" />
                </HierarchicalDataTemplate>
                <DataTemplate DataType="{x:Type structure:NewsPaperBlock}">
                    <TextBlock Text="{Binding Name}" Tag="{Binding Object}" Foreground="#2b5797" />
                </DataTemplate>
            </TreeView.Resources>
        </TreeView>

ArticlesTreeView.SelectedItem 中存储类NewsPaperDocument, NewsPaperPage, etc 的实例。如何获得与SelectedItem 关联的TreeViewItem?我尝试使用VisualTreeHelper.GetParent(elem);,但SelectedItem 没有DependencyObject 类型

UPD1 添加简单示例,演示问题。 itemArticlesTreeView_SelectedItemChanged 中总是null

XAML

<Window x:Class="TestTree.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:testTree="clr-namespace:TestTree"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <TreeView x:Name="ArticlesTreeView" Grid.Column="0" AllowDrop="True" SelectedItemChanged="ArticlesTreeView_SelectedItemChanged">
        <TreeView.Resources>
            <HierarchicalDataTemplate   DataType="{x:Type testTree:A}" ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding Name}" FontWeight="Bold" />
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="{x:Type testTree:B}" ItemsSource="{Binding Children}">
                <TextBlock Text="{Binding Name}" Foreground="#00a300" />
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type testTree:C}">
                <TextBlock Text="{Binding Name}" Foreground="#2b5797" />
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>
</Grid>

CS

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace TestTree
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var a = new A
            {
                Name = "a",
                Children = new List<B>
                {
                    new B
                    {
                        Name = "b1",
                        Children = new List<C>
                        {
                            new C{Name = "c1"},
                            new C{Name = "c2"},
                            new C{Name = "c3"}
                        },
                    },
                    new B
                    {
                        Name = "b2",
                        Children = new List<C>
                        {
                            new C{Name = "c1"},
                            new C{Name = "c2"},
                            new C{Name = "c3"}
                        },
                    },
                    new B
                    {
                        Name = "b3",
                        Children = new List<C>
                        {
                            new C{Name = "c1"},
                            new C{Name = "c2"},
                            new C{Name = "c3"}
                        },
                    }
                }
            };
            ArticlesTreeView.ItemsSource = new List<A> { a };
        }

        private void ArticlesTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            ItemContainerGenerator gen = ArticlesTreeView.ItemContainerGenerator;
            var item = gen.ContainerFromItem(ArticlesTreeView.SelectedItem);
        }
    }

    internal class A
    {
        public string Name { set; get; }

        public List<B> Children { set; get; }
    }

    internal class B
    {
        public string Name { set; get; }

        public List<C> Children { set; get; }
    }

    internal class C
    {
        public string Name { set; get; }
    }
}

【问题讨论】:

  • ArticlesTreeView.SelectedItemTreeViewItem。你的问题是得到TreeView?我不确定我是否理解您的问题
  • @YuvalItzchakov 如果你通过手动添加TreeViewItem's 来创建你的树,那么它就可以了。但我使用HierarchicalDataTemplate,我的树会从集合中自动创建。 SelectedItemSelectedValue 的类型是 NewsPaperBlock 或 etc

标签: c# wpf treeview treeviewitem visualtreehelper


【解决方案1】:

如果我的理解正确,您想从 SelectedItem 中检索 TreeViewItem

这样你就可以使用ItemContainerGenerator

        ItemContainerGenerator gen = ArticlesTreeView.ItemContainerGenerator;
        TreeViewItem item = gen.ContainerFromItem(ArticlesTreeView.SelectedItem) as TreeViewItem;

从嵌套项中获取 TreeViewItem

由于每个TreeViewItem 都有自己的ItemContainerGenerator,所以为了从嵌套项中找到容器,我们需要递归树的深度

    private void ArticlesTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        var item = ContainerFromItem(ArticlesTreeView.ItemContainerGenerator, ArticlesTreeView.SelectedItem);
    }

    private static TreeViewItem ContainerFromItem(ItemContainerGenerator containerGenerator, object item)
    {
        TreeViewItem container = (TreeViewItem)containerGenerator.ContainerFromItem(item);
        if (container != null)
            return container;

        foreach (object childItem in containerGenerator.Items)
        {
            TreeViewItem parent = containerGenerator.ContainerFromItem(childItem) as TreeViewItem;
            if (parent == null)
                continue;

            container = parent.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
            if (container != null)
                return container;

            container = ContainerFromItem(parent.ItemContainerGenerator, item);
            if (container != null)
                return container;
        }
        return null;
    }

【讨论】:

  • 我试了一下,但是当ArticlesTreeView.SelectedItem not null 时,gen.ContainerFromItem(ArticlesTreeView.SelectedItem) 返回 null
  • 这可能是由于虚拟化而发生的。这里重要的一点是 TreeViewItem 或 Container 只能在生成时检索,因此应该加载项目和/或在视图中,如果不是,您可以在获取容器之前滚动到项目。只需确保您在可以看到 Container(TreeViewItem) 时检索它,否则有可能 Container 尚未创建或已被回收到其他项目。
  • Snoop 中创建了所有TreeViewItems,并且所选元素在我的视图中可见
  • 您是否可以发布可以重现该问题的代码的工作示例?让我们看看我们如何为您解决此问题。
  • 在第一条消息中添加样本
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 1970-01-01
  • 2021-10-15
  • 2011-08-23
  • 1970-01-01
相关资源
最近更新 更多