我有一个TreeView,它将包含许多不同种类的树节点和上下文菜单。不同类型的树节点的上下文菜单将不同,但也将共享一些部分。我只想定义一次常用菜单部分。因此,我将一些常见的菜单项数组定义为资源,然后使用CompositeCollection将它们拉入每个上下文菜单。我的场景的一个非常简单的例子如下:
<Window x:Class="TreeViewCompositeContextMenuProblem.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TreeViewCompositeContextMenuProblem"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<x:Array x:Key="EditMenuItems" Type="{x:Type MenuItem}">
<MenuItem Header="Copy" />
<MenuItem Header="Paste" />
<MenuItem Header="Delete" />
</x:Array>
<x:Array x:Key="CommonMenuItems" Type="{x:Type MenuItem}">
<MenuItem Header="View properties" />
</x:Array>
<HierarchicalDataTemplate DataType="{x:Type local:ItemViewModel}" ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Path=Name}">
<TextBlock.ContextMenu>
<ContextMenu>
<ContextMenu.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{StaticResource EditMenuItems}" />
<Separator />
<CollectionContainer Collection="{StaticResource CommonMenuItems}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<TreeView Name="treeView">
</TreeView>
</Grid>
</Window>
其中ItemViewModel简单地定义为
public class ItemViewModel
{
public ObservableCollection<ItemViewModel> Children {get; set; }
public string Name {get;set;}
public ItemViewModel(string name)
{
Children = new ObservableCollection<ItemViewModel>();
Name = name;
}
}
然后我按如下方式绑定treeView:
var vm = new ItemViewModel("root");
var a = new ItemViewModel("a");
var b = new ItemViewModel("b");
var c = new ItemViewModel("c");
vm.Children.Add(a);
vm.Children.Add(b);
b.Children.Add(c);
treeView.ItemsSource = new List<ItemViewModel>() { vm };
现在,如果在运行应用程序时,我打开项目“a”的上下文菜单,然后打开项目“b”,再打开项目“a”,我得到以下结果:
我想我对CompositeCollection的使用引入了某种与数据模板不兼容的共享。有谁知道这里出了什么问题?
谢谢!
答案 0 :(得分:2)
如果上下文菜单在上下文视觉中共享,则会更好地管理它们,前提是它们的基础项源是共享的菜单项列表(就像您的情况一样)。因此,基本上在您的情况下,上下文菜单应声明为静态资源,然后单独在所有文本块之间共享。
<Window.Resources>
....
<ContextMenu x:Key="MyContextMenu">
<ContextMenu.ItemsSource>
<CompositeCollection>
<CollectionContainer
Collection="{StaticResource EditMenuItems}" />
<Separator />
<CollectionContainer
Collection="{StaticResource CommonMenuItems}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
<HierarchicalDataTemplate
DataType="{x:Type local:ItemViewModel}"
ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Path=Name}"
ContextMenu="{StaticResource MyContextMenu}">
....
</HierarchicalDataTemplate>
</Window.Resources>