为数据网格行创建上下文菜单 [英] Create contextmenus for datagrid rows

查看:17
本文介绍了为数据网格行创建上下文菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个可能有很多行的数据网格.当用户右键单击其中一行时,我需要为每一行显示一个上下文菜单,并在用户单击选项时执行一个操作(相同的操作,但根据当前选定的行不同的数据项).

I have a datagrid that potentially can have many rows. As the user right clicks one of the rows, I need to show a context menu for each of the rows and perform an action (same action but different data item according to the current selected row) when the user clicks the option.

对此的最佳策略是什么?

What is the best strategy for this?

即使我使用 ContextMenuOpening 事件创建菜单,我也担心每行的 ContextMenu 是矫枉过正,有点像上下文菜单的延迟加载".我应该只为数据网格使用一个 ContextMenu 吗?但是有了这个,我将有更多关于点击事件的工作,以确定正确的行等.

I'm fearing that a ContextMenu for each row is overkill even though I'm creating the menu using the ContextMenuOpening event, sort of a "lazy load" for the context menu. Should I only use one ContextMenu for the datagrid? But with this I would have some more work regarding the click event, to determine the correct row, etc.

推荐答案

据我所知,有些动作会根据行被禁用或启用,所以在单个 ContextMenu 用于 DataGrid.

As far as I know, some of the actions will be disabled or enabled depending on the row, so there is no point in a single ContextMenu for a DataGrid.

我有一个行级上下文菜单的示例.

I have an example of the row-level context menu.

<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 必须使用命令绑定到视图模型列表:

The DataGrid must have a binding to a list of view models with commands:

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 的资源集合中创建的,我认为只有一个对象通过引用而不是通过值与数据网格行连接.

The context menu is created in the resources collection of the UserControl and I think there is only one object which is connected with datagrid rows by reference, not by value.

这是 MainViewModelCommand 的另一个 ContextMenu 示例.我想 DataGrid 有一个正确的视图模型作为 DataContext,CommandParameter 属性也必须放在 Command 属性之前:

Here is another example of ContextMenu for a Command inside a MainViewModel. I suppose that DataGrid has a correct view model as the DataContext, also the CommandParameter attribute must be placed before the Command attribute:

    <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; }
}

但是存在一个问题,如果 CanExecute 返回 false,MenuItem 不会显示为禁用项.可能的解决方法是在 ItemModel 中使用 ParentModel 属性,但它与第一​​个解决方案没有太大区别.以下是上述解决方案的示例:

But there is a problem that MenuItem isn't displayed as a disabled item if CanExecute returns false. The possible workaround is using a ParentModel property inside the ItemModel, but it doesn't differ much from the first solution. Here is example of above-described solution:

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()};

XAML 中的 MenuItem 会更简单:

And MenuItem in XAML will be simplier:

<MenuItem Header="Edit" CommandParameter="{Binding}"
              Command="{Binding ParentViewModel.DataGridActionCommand}" />

这篇关于为数据网格行创建上下文菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆