为datagrid行创建contextmenus [英] Create contextmenus for datagrid rows

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

问题描述

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



这是最好的策略是什么?



我担心每一行的ContextMenu都会过高,即使我'使用ContextMenuOpening事件创建菜单,为上下文菜单排序一个延迟加载。我应该只为DataGrid使用一个ContextMenu吗?但是,为了确定正确的行等,我将会有更多关于点击事件的工作。

解决方案

我知道,一些操作将被禁用或启用,具体取决于行,因此在 DataGrid 中单个 ContextMenu code>。



我有一个行级上下文菜单的例子。

 < UserControl.Resources> 
< ContextMenu x:Key =RowMenuDataContext ={Binding PlacementTarget.DataContext,RelativeSource = {RelativeSource Self}}>
< MenuItem Header =EditCommand ={Binding EditCommand}/>
< / ContextMenu>
< Style x:Key =DefaultRowStyleTargetType ={x:Type DataGridRow}>
< Setter Property =ContextMenuValue ={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;组; }
public string标题{get;组; }
public ICommand EditCommand {get;组; }
}

上下文菜单是在$ $ c $的资源集合中创建的c> UserControl ,我认为只有一个对象通过引用与datagrid行连接,而不是通过值。



这是另一个例子 ContextMenu for a Command in a MainViewModel 。我认为 DataGrid 具有正确的视图模型作为 DataContext ,CommandParameter属性也必须放在Command属性之前:

 < ContextMenu x:Key =RowMenuDataContext ={Binding PlacementTarget.DataContext,RelativeSource = {RelativeSource Self} }> 
< MenuItem Header =编辑CommandParameter ={Binding}
Command ={Binding DataContext.DataGridActionCommand,RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = DataGrid}}/>
< / ContextMenu>

型号:

 code> public class MainViewModel 
{
public MainViewModel()
{
this.DataGridActionCommand = new DelegateCommand< ItemModel>(m => MessageBox.Show(m。标题),m => m!= null&& m.Id!= 2);
}

public DelegateCommand< ItemModel> DataGridActionCommand {get;组; }
public List< ItemModel>物品{get;组; }
}

public class ItemModel
{
public int Id {get;组; }
public string标题{get;组; }
}

但是有一个问题, MenuItem 不显示为禁用项,如果 CanExecute 返回false。可能的解决方法是在 ItemModel 中使用 ParentModel 属性,但与第一个解决方案没有太大差异。
这是上述解决方案的示例:

  public class ItemModel 
{
public int Id {get;组; }
public string标题{get;组; }
public MainViewModel ParentViewModel {get;组; }
}

//在代码隐藏的某处,创建主视图模型
//并强制子项目将此模型用作父模型
var mainModel = new MainViewModel {Items = items.Select(item => new ItemViewModel(item,mainModel))。ToList()};

而XAML中的MenuItem将更简单:

 < MenuItem Header =编辑CommandParameter ={Binding}
Command ={Binding ParentViewModel.DataGridActionCommand}/>


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?

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.

解决方案

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}"/>

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

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.

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>

Models:

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

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

And MenuItem in XAML will be simplier:

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

这篇关于为datagrid行创建contextmenus的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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