ContextMenu с CompositeCollection в TreeView: пункты меню исчезают - PullRequest
2 голосов
/ 23 октября 2011

У меня есть 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 };

Теперь, если при запуске приложения я открываю контекстное меню для элемента «а», затем для элемента «б» и затем снова для элемента «а», я получаю следующий результат:

bug

Я полагаю, что мое использование CompositeCollection вводит некоторый вид обмена, который не очень хорошо работает с шаблонами данных. Кто-нибудь знает, что здесь не так?

Спасибо!

1 Ответ

2 голосов
/ 24 октября 2011

Контекстные меню лучше управляются, если они совместно используются среди контекстуальных визуальных элементов при условии, что источником их базовых элементов является общий список пунктов меню (как в вашем случае).Так что в основном в вашем случае контекстное меню должно быть объявлено как статический ресурс, а затем разделено между всеми текстовыми блоками индивидуально.

  <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> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...