用于MVVM的WPF MenuItem模板

时间:2011-04-07 18:11:21

标签: xaml mvvm datatemplate

我无法编写xaml表示以允许绑定到我的后台ViewModel以用于级联菜单

这是VM:

public class MenuNode
{
  public string Header {get;}
  public List<MenuNode> Items {get;}
}
我拥有的xaml就是这样:

<ContextMenu ItemsSource="{Binding Choices}" >
    <ContextMenu.Resources>
        <DataTemplate DataType="{x:Type vmi:MenuNode}">
            <MenuItem Header="{Binding Header}" ItemsSource="{Binding Items}"/>
        </DataTemplate> 
    </ContextMenu.Resources>
</ContextMenu>

当菜单弹出时,我会得到带箭头的第一级条目(表示应该有一个子菜单),但当我将鼠标悬停在菜单上时,它不会显示子菜单项。

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

好的,这是问题所在:

出于某种原因,MenuItems生成的DataTemplate被包裹在另一个MenuItem内(结果是嵌套MenuItems)。子项目未被打开,因为外部MenuItem没有子项。

解决方案是改为使用HierarchicalDataTemplate

<ContextMenu ItemsSource="{Binding Choices}" >
    <ContextMenu.Resources>
        <HierarchicalDataTemplate DataType="{x:Type vmi:MenuNode}" ItemsSource="{Binding Items}">
            <TextBlock Text="{Binding Header}"/>
        </HierarchicalDataTemplate> 
    </ContextMenu.Resources>
</ContextMenu>

答案 1 :(得分:4)

我对MenuItems和MVVM的看法(将图标放在那里并不容易)

  public class MenuItemVM
  {
    public string Text { get; set; }
    public List<MenuItemVM> Children { get; set; }
    public ICommand Command { get; set; }
    public ImageSource Icon { get; set; }
  }

public IList<MenuItemVM> AddContextMenu { get; set; }

查看:

<Image x:Key="MenuItemIcon"
       x:Shared="false"
       Source="{Binding Icon}"
       Height="16px"
       Width="16px"/>

<Style x:Key="ContextMenuItemStyle" TargetType="{x:Type MenuItem}">
  <Setter Property="MenuItem.Icon" Value="{StaticResource MenuItemIcon}"/>
  <Setter Property="MenuItem.Command" Value="{Binding Command}" />
  <Style.Triggers>
    <!-- insert a null in ItemsSource if you want a separator -->
    <DataTrigger Binding="{Binding}" Value="{x:Null}">
      <Setter Property="Template" >
        <Setter.Value>
          <ControlTemplate>
            <Separator Style="{StaticResource {x:Static MenuItem.SeparatorStyleKey}}"/>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </DataTrigger>
  </Style.Triggers>
</Style>

将上下文菜单添加到您的UI

<ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}"
             ItemsSource="{Binding AddContextMenu}">
  <ContextMenu.Resources>
    <HierarchicalDataTemplate DataType="{x:Type vmp:MenuItemVM}"
                              ItemsSource="{Binding Children}">
      <TextBlock Text="{Binding Text}"/>
    </HierarchicalDataTemplate>
  </ContextMenu.Resources>
</ContextMenu>

答案 2 :(得分:1)

如果要在初始化绑定后将节点添加到列表中,请尝试使用ObservableCollection<MenuNode>而不是List<MenuNode>,除非您要触发INotifyCollectionChanged {{{},否则不会更新项目集合1}}这样做。)