wpf如何将一个TreeView绑定到另一个TreeView

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了wpf如何将一个TreeView绑定到另一个TreeView相关的知识,希望对你有一定的参考价值。

我正在尝试将TreeView t2绑定到xaml中的TreeView t1,如下所示:

<Window x:Class="WpfApp2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp2"
    mc:Ignorable="d"
    Title="MainWindow" Height="620" Width="600">
<Window.Resources>
    <HierarchicalDataTemplate DataType="{x:Type TreeViewItem}" ItemsSource="{Binding Items}">
        <StackPanel Orientation="Horizontal" >
            <TextBlock Background="AliceBlue" Text="{Binding Path=Header, Mode=TwoWay}" Width="220"/>
        </StackPanel>
    </HierarchicalDataTemplate>
</Window.Resources>
<StackPanel>
    <TreeView x:Name="t1">
        <TreeView.Items>
            <TreeViewItem Header="a"></TreeViewItem>
            <TreeViewItem Header="b"></TreeViewItem>
        </TreeView.Items>
    </TreeView>
    <TreeView x:Name="t2" ItemsSource="{Binding Items, ElementName=t1}"></TreeView>
</StackPanel>

我期望t2t1具有相同数量的节点。但结果是,t1的所有节点都被删除了。 Why

我期待的结果:

enter image description here

实际结果:

enter image description here

答案

我期望t2t1具有相同数量的节点。但结果是,t1的所有节点都被删除了。为什么?

因为视觉元素的实例(例如TreeViewItem)只能在可视树中出现一次。一个元素只能有一个可视父级,在这种情况下,项目将从第一个TreeView中删除并添加到第二个。

因此,您需要克隆您希望能够在TreeViewItem中显示的每个TreeViews元素。

另一答案

回答我自己的问题:

从源代码中找到答案。看起来它是设计的(我仍然不明白为什么它的设计是这样的)。如果给定的项目是TreeViewItem,那么它将用作节点容器而不是创建新的容器。

ItemsControl.cs(第1323行)

/// <summary>
    /// Return the element used to display the given item
    /// </summary>
    DependencyObject IGeneratorHost.GetContainerForItem(object item)
    {
        DependencyObject container;

        // use the item directly, if possible (bug 870672)
        if (IsItemItsOwnContainerOverride(item))
            container = item as DependencyObject;
        else
            container = GetContainerForItemOverride();

        // the container might have a parent from a previous
        // generation (bug 873118).  If so, clean it up before using it again.
        //
        // Note: This assumes the container is about to be added to a new parent,
        // according to the ItemsControl/Generator/Container pattern.
        // If someone calls the generator and doesn't add the container to
        // a visual parent, unexpected things might happen.
        Visual visual = container as Visual;
        if (visual != null)
        {
            Visual parent = VisualTreeHelper.GetParent(visual) as Visual;
            if (parent != null)
            {
                Invariant.Assert(parent is FrameworkElement, SR.Get(SRID.ItemsControl_ParentNotFrameworkElement));
                Panel p = parent as Panel;
                if (p != null && (visual is UIElement))
                {
                    p.Children.RemoveNoVerify((UIElement)visual);
                }
                else
                {
                    ((FrameworkElement)parent).TemplateChild = null;
                }
            }
        }

        return container;
    }

TreeView(第400行)

public class TreeView : ItemsControl {
    ...
    /// <summary>
    ///     Returns true if the item is or should be its own container.
    /// </summary>
    /// <param name="item">The item to test.</param>
    /// <returns>true if its type matches the container type.</returns>
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is TreeViewItem;
    }
    ....
}

以上是关于wpf如何将一个TreeView绑定到另一个TreeView的主要内容,如果未能解决你的问题,请参考以下文章

WPF TreeView 数据绑定隐藏/显示展开/折叠图标

wpf如何根据输入信息动态生成treeview

WPF TreeView HierarchicalDataTemplate - 绑定到具有多个子集合的对象

wpf treeview 数据绑定 递归绑定节点

WPF TreeView绑定数据

WPF TreeView绑定数据