我正在尝试将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>
我希望t2
的节点数与t1
相同。但是结果是t1
的所有节点都被删除了。 Why
?
我预期的结果:
实际结果:
答案 0 :(得分:1)
我希望
t2
的节点数与t1
相同。但是结果是t1
的所有节点都被删除了。为什么?
因为视觉元素的实例,例如TreeViewItem
只能一次出现在视觉树中。一个元素最多只能有一个个可视父元素,在这种情况下,这些元素将从第一个TreeView
中删除,然后添加到第二个。
因此,您需要克隆要在两个TreeViewItem
中都显示的每个TreeViews
元素。
答案 1 :(得分:1)
要回答我自己的问题:
从源代码中找到答案。似乎是设计使然(我仍然不明白为什么要这样设计)。如果给定的项目为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;
}
....
}