C# MVVM中的上下文菜单

C# MVVM中的上下文菜单,c#,wpf,mvvm,binding,contextmenu,C#,Wpf,Mvvm,Binding,Contextmenu,我想将contextmenu绑定到命令列表 <Grid.ContextMenu> <ContextMenu ItemsSource="{Binding ItemContextCommands, Converter={StaticResource commandToStringConverter}}"> <ContextMenu.ItemTemplate > <DataTemplate

我想将contextmenu绑定到命令列表

<Grid.ContextMenu>
    <ContextMenu ItemsSource="{Binding ItemContextCommands, Converter={StaticResource commandToStringConverter}}">
            <ContextMenu.ItemTemplate >
                    <DataTemplate DataType="MenuItem">
                            <MenuItem Command="{Binding}"></MenuItem>
                        </DataTemplate>
                </ContextMenu.ItemTemplate>
        </ContextMenu>
</Grid.ContextMenu>

commandToStringConverter
仅将命令列表转换为对列表中的每个命令调用
ToString()
的字符串列表

如何实现调用每个
菜单项中的
命令

我将使用一个小的“视图模型”来保存此类命令的信息

class ContextAction : INotifyPropertyChanged
{
    public string Name;
    public ICommand Action;
    public Brush Icon;
}
在视图模型内创建一个集合,该集合应获得如下上下文操作

ObservableCollection<ContextAction> Actions {get;set;}

contextmenu项的
ItemTemplate
现在可以访问名称、命令以及您可能需要的任何其他内容。更改
CommandParameter
可能也很有用,这样它就可以使用actions所属元素调用命令,而不是使用action本身。

我使用了如下方法:

public class ContextMenuVM
{ 
    public string Displayname {get;set;}
    public ICommand MyContextMenuCommand {get;set;}
}
在您的contextmenu数据上下文中:

public ObservableCollection<ContextMenuVM> MyCommandList {get;set;}
publicobservableCollection MyCommandList{get;set;}
在您的xaml中

<ContextMenu ItemsSource="{Binding MyCommandList}">
        <ContextMenu.ItemTemplate >
                <DataTemplate DataType="MenuItem">
                        <MenuItem Header="{Binding Displayname}" Command="{Binding MyContextMenuCommand}"></MenuItem>
                    </DataTemplate>
            </ContextMenu.ItemTemplate>
    </ContextMenu>


它是在没有ide的情况下编写的,因此可能存在一些语法错误。

下面是@blindmils解决方案的改进XAML版本:

<ContextMenu ItemsSource="{Binding MyCommandList}">
    <ContextMenu.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Header" Value="{Binding Displayname}" />
            <Setter Property="Command" Value="{Binding MyContextMenuCommand }" />
        </Style>
    </ContextMenu.ItemContainerStyle>
</ContextMenu>


您可能应该考虑使用另一个转换器,将每个{Binding}转换为实际的命令调用。转换器返回函数列表?有人知道如何处理带有分隔符和子菜单的ContextMenu吗?此解决方案似乎只对同质对象集有用。子菜单也同样简单。您只需为ContextMenu提供一个ItemContainerStyle和ItemsSource的setter,并在ContextAction中绑定到ObservableCollection类型的新属性。有关分隔符,请参阅解决方案。此解决方案具有MenuItem的嵌套控件
<ContextMenu ItemsSource="{Binding MyCommandList}">
    <ContextMenu.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Setter Property="Header" Value="{Binding Displayname}" />
            <Setter Property="Command" Value="{Binding MyContextMenuCommand }" />
        </Style>
    </ContextMenu.ItemContainerStyle>
</ContextMenu>