2011-10-23 8 views
1

私はコンテキストメニューでさまざまな種類のツリーノードを含むTreeViewを持っています。さまざまなタイプのツリーノードのコンテキストメニューは異なりますが、いくつかのセクションも共有されます。私は共通のメニューセクションを一度定義したいだけです。したがって、メニュー項目の一般的な配列をリソースとして定義し、CompositeCollectionを使用して各コンテキストメニューにプルダウンします。次のようにItemViewModelは単にTreeViewのCompositeCollectionを使用したContextMenu:メニュー項目が消えます

public class ItemViewModel 
{ 
    public ObservableCollection<ItemViewModel> Children {get; set; } 
    public string Name {get;set;} 

    public ItemViewModel(string name) 
    { 
     Children = new ObservableCollection<ItemViewModel>(); 
     Name = name; 
    } 
} 

として定義されて

<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> 

は、私は、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"のコンテキストメニューが開き、次の結果が得られます。

bug

私のCompositeCollectionを使用すると、データテンプレートではうまくいきません。誰がここで間違っているか知っていますか?

ありがとうございます!

答えて

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> 
+3

これは良い点です。ありがとうございます。しかし、複数のコンテキストメニューが "EditMenuItems"コレクションを使用している場合、メニュー間で個々のメニュー項目の共有が導入されるため、問題は残っています。 x:Array要素にx:Shared = "False"を追加すると助けになりました。これは、配列を参照する代わりに、配列をそのままコピーするようにXAMLパーサに指示します。 –

関連する問題