为datagrid行创建contextmenus [英] Create contextmenus for datagrid rows
问题描述
这是最好的策略是什么?
我担心每一行的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屋!