J'ai un TreeView qui va contenir de nombreux types de nœuds d'arbre avec des menus contextuels. Les menus contextuels pour les différents types de nœuds d'arbres seront différents, mais partageront également certaines sections. Je veux seulement définir les sections du menu commun une fois. Je définis donc des tableaux communs d'éléments de menu en tant que ressource, puis les place dans chaque menu contextuel à l'aide d'une collection composite. Un exemple très simple de mon scénario est comme suit:ContextMenu avec CompositeCollection dans TreeView: les éléments de menu disparaissent
<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>
où le ItemViewModel est simplement défini comme
public class ItemViewModel
{
public ObservableCollection<ItemViewModel> Children {get; set; }
public string Name {get;set;}
public ItemViewModel(string name)
{
Children = new ObservableCollection<ItemViewModel>();
Name = name;
}
}
Je lie alors le treeView comme suit:
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 };
Maintenant, si , lors de l'exécution de l'application, j'ouvre le menu contextuel sur le point "a", puis sur le point "b" puis sur le point "a" à nouveau, j'obtiens le résultat suivant:
Je suppose que mon utilisation de CompositeCollection introduit un type de partage qui ne joue pas bien avec les modèles de données. Est-ce que quelqu'un sait ce qui ne va pas ici?
Merci!
C'est un bon point - merci. Toutefois, il y aura toujours des problèmes si plusieurs menus contextuels utilisent les collections "EditMenuItems", car cela introduira le partage des éléments de menu individuels entre les menus. J'ai trouvé que l'ajout de x: Shared = "False" aux éléments x: Array aidé. Cela demande à l'analyseur XAML de copier les tableaux verbatim au lieu de les référencer. –