Xaml MVVM的WPF菜单项模板

Xaml MVVM的WPF菜单项模板,xaml,mvvm,datatemplate,Xaml,Mvvm,Datatemplate,我在编写xaml表示以允许绑定到我的后台ViewModel以用于级联菜单时遇到问题 以下是虚拟机: public class MenuNode { public string Header {get;} public List<MenuNode> Items {get;} } 公共类菜单节点 { 公共字符串头{get;} 公共列表项{get;} } 我拥有的xaml是: <ContextMenu ItemsSource="{Binding Choices}" >

我在编写xaml表示以允许绑定到我的后台ViewModel以用于级联菜单时遇到问题

以下是虚拟机:

public class MenuNode
{
  public string Header {get;}
  public List<MenuNode> Items {get;}
}
公共类菜单节点
{
公共字符串头{get;}
公共列表项{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>

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


有什么想法吗?

尝试使用
ObservableCollection
而不是
List
如果在绑定初始化后将节点添加到列表中,则除非您触发
INotifyCollectionChanged
ObservableCollection
执行此操作)。

好的,问题是:

由于某种原因,由您的
数据模板生成的
菜单项
被包装在另一个
菜单项
中(结果是嵌套的
菜单项
)。未打开子项,因为外部
菜单项没有子项

解决方案是使用
层次结构数据模板

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

我对MenuItems和MVVM的看法(在其中放置图标并不容易)

public类MenuItemVM
{
公共字符串文本{get;set;}
公共列表子项{get;set;}
公共ICommand命令{get;set;}
公共图像源图标{get;set;}
}
公共IList AddContextMenu{get;set;}
视图:


将contextmenu添加到您的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>


是否可能在绑定初始化后添加项目?也许你需要使用ObservableCollection而不是List来通知items集合。MenuItem和TabItem item生成的诀窍是填充标题/图标区域。您必须使用ItemContainerStyle来完成,这很棘手。这不是问题,因为对象是在绑定发生之前初始化的好吧,我想可能不会。让我检查一下。乍一看,你的代码看起来很棒。我将把它切换到ObservableCollection,看看它是否有区别,也许它应该是HierarchycalTemplate?宾果。它应该是HierarchycalDataTemplate。您的XAML看起来应该可以工作,但由于某种原因,模板中的MenuItems被项容器包装到另一个MenuItem中。
<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>
<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>