我有一个可能有很多行的数据网格。当用户右键单击其中一行时,我需要显示每个行的上下文菜单,并在用户单击选项时执行操作(根据当前所选行执行相同操作但不同的数据项)。
最佳策略是什么?
我担心每行的ContextMenu都是矫枉过正,即使我使用ContextMenuOpening事件创建菜单,也就是上下文菜单的“延迟加载”。我应该只为数据网格使用一个ContextMenu吗?但是有了这个,我会对click事件有更多的工作,以确定正确的行等。
答案 0 :(得分:34)
据我所知,某些操作将会被禁用或启用,具体取决于行,因此ContextMenu
的单DataGrid
内没有任何意义。
我有一个行级上下文菜单的例子。
<UserControl.Resources>
<ContextMenu x:Key="RowMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Edit" Command="{Binding EditCommand}"/>
</ContextMenu>
<Style x:Key="DefaultRowStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />
</Style>
</UserControl.Resources>
<DataGrid RowStyle="{StaticResource DefaultRowStyle}"/>
DataGrid
必须使用命令绑定到视图模型列表:
public class ItemModel
{
public ItemModel()
{
this.EditCommand = new SimpleCommand
{
ExecuteDelegate = _ => MessageBox.Show("Execute"),
CanExecuteDelegate = _ => this.Id == 1
};
}
public int Id { get; set; }
public string Title { get; set; }
public ICommand EditCommand { get; set; }
}
上下文菜单是在UserControl
的资源集合中创建的,我认为只有一个对象通过引用与datagrid行连接,而不是通过值。
以下是ContextMenu
内Command
的{{1}}的另一个示例。我认为MainViewModel
具有正确的视图模型DataGrid
,CommandParameter属性也必须放在Command属性之前:
DataContext
型号:
<ContextMenu x:Key="RowMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Edit" CommandParameter="{Binding}"
Command="{Binding DataContext.DataGridActionCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
</ContextMenu>
但如果public class MainViewModel
{
public MainViewModel()
{
this.DataGridActionCommand = new DelegateCommand<ItemModel>(m => MessageBox.Show(m.Title), m => m != null && m.Id != 2);
}
public DelegateCommand<ItemModel> DataGridActionCommand { get; set; }
public List<ItemModel> Items { get; set; }
}
public class ItemModel
{
public int Id { get; set; }
public string Title { get; set; }
}
返回false,则存在MenuItem
未显示为已禁用项的问题。可能的解决方法是在CanExecute
内使用ParentModel
属性,但与第一个解决方案没有太大区别。
以下是上述解决方案的示例:
ItemModel
XAML中的MenuItem将更简单:
public class ItemModel
{
public int Id { get; set; }
public string Title { get; set; }
public MainViewModel ParentViewModel { get; set; }
}
//Somewhere in the code-behind, create the main view model
//and force child items to use this model as a parent model
var mainModel = new MainViewModel { Items = items.Select(item => new ItemViewModel(item, mainModel)).ToList()};