动态绑定到窗口菜单项上的ViewModel命令

5

正在使用MVVM结构开发WPF应用程序。

我的窗口显示菜单和当前的ViewModel。在菜单的某个菜单项中,我想列出当前ViewModel中找到的一些命令。在菜单中列出的命令将根据ViewModel而改变。

我已经成功地实现了这个功能,但是样式混乱了——命令菜单项在另一个菜单框中或其他地方。我会附上一张截图。

我将ViewModel的ICommand对象(在这种情况下是RelayCommands)封装在CommandViewModel中,它们公开了我想要在菜单上显示的命令和显示字符串。这些CommandViewModel在一个列表中:CurrentWorkspace.AdditionalOptionsCommands

以下是菜单的XAML。像我说的那样,它可以工作,显示正确的项目并执行命令。只是显示不正确——有人能告诉我为什么以及如何修复吗?请参见截图。

<Menu>
    <MenuItem Header="_Additional Options..." ItemsSource="{Binding Path=CurrentWorkspace.AdditionalOptionsCommands}">
        <MenuItem.ItemTemplate>
            <DataTemplate DataType="{x:Type vm:CommandViewModel}">
                <MenuItem Header="{Binding Path=DisplayText}" Command="{Binding Path=Command}"/>
            </DataTemplate>
        </MenuItem.ItemTemplate>
    </MenuItem>
    <MenuItem Header="_Testing">
        <MenuItem Header="This looks right" />
        <MenuItem Header="This looks right" />
    </MenuItem>   
</Menu>  

当前外观:

当前外观

期望的外观:

期望的外观

1个回答

8
这是因为当您通过ItemsSource指定菜单项时,每个项目都会自动包装成一个MenuItem对象。这样,DataTemplateMenuItem元素)中定义的内容将被再次包装在一个MenuItem中。
相反,您需要做的是定义一个MenuItem样式,其中设置到视图模型属性的绑定,并将此样式作为ItemContainerStyle应用于父级MenuItem,而不是定义DataTemplate
<Window.Resources>
    <Style x:Key="CommandMenuItemStyle"
           TargetType="{x:Type MenuItem}">
         <Setter Property="Header"
                 Value="{Binding Path=DisplayText}"/> 
         <Setter Property="Command"
                 Value="{Binding Path=Command}"/>
    </Style>
</Window.Resources>
...
<Menu>
    <MenuItem Header="_Additional Options..." 
              ItemsSource="{Binding Path=CurrentWorkspace.AdditionalOptionsCommands}" 
              ItemContainerStyle="{StaticResource CommandMenuItemStyle}"/>
    <MenuItem Header="_Testing">
        <MenuItem Header="This looks right" />
        <MenuItem Header="This looks right" />
    </MenuItem>   
</Menu>   

访问http://drwpf.com/blog/2008/03/25/itemscontrol-i-is-for-item-container/,深入了解如何使用ItemsControl控件处理项目容器的工作原理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接