Por lo que sé, algunas de las acciones se desactivarán o habilitarán dependiendo de la fila, por lo que no hay apunte en un solo ContextMenu
para un DataGrid
.
Tengo un ejemplo del menú contextual a nivel de fila.
<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}"/>
El DataGrid
debe tener una unión a una lista de modelos de vista con los comandos:
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; }
}
Se crea el menú de contexto en la colección de recursos de la UserControl
y creo que sólo hay un objeto que está conectado con las filas de la cuadrícula de datos por referencia, no por valor.
Aquí hay otro ejemplo de ContextMenu
para Command
dentro de MainViewModel
. Supongo que DataGrid
tiene una vista de modelo correcto como la DataContext
, también el atributo CommandParameter debe colocarse antes del atributo de comando:
<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>
modelos:
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; }
}
pero hay un problema que MenuItem
ISN' t se muestra como un elemento deshabilitado si CanExecute
devuelve falso. La posible solución alternativa es usar una propiedad ParentModel
dentro del ItemModel
, pero no difiere mucho de la primera solución. Aquí es ejemplo de la solución descrita anteriormente:
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()};
Y Menultem en XAML habrá más simple:
<MenuItem Header="Edit" CommandParameter="{Binding}"
Command="{Binding ParentViewModel.DataGridActionCommand}" />
Gracias por la muestra, voy a dar una oportunidad. Pero, como usted, tengo la misma duda, ¿hay solo un objeto del menú contextual? Tendré que profundizar en esto. – Jay
Probé esto, y comparando el Código Hash de los ContextMenus de cada una de las filas, proporciona el mismo valor, por lo que debería ser el mismo objeto. ¡Bonito! ¿Realmente necesito un comando para cada fila? Quería usar como un comando principal que se encuentra en la parte superior, dentro del modelo de vista principal. ¿Se puede hacer esto simplemente ajustando la vinculación de comandos en el elemento de menú? ¡No puedo conseguir que funcione! maldición ... – Jay
@Jay ¿Te refieres a un RoutedCommand estático? En realidad, es posible usar manejadores de eventos o comandos globales en lugar de comandos a nivel de fila. Trataré de implementar algo similar mañana, y si pudieras agregar el código de tu comando a la pregunta, eso me ayudaría. – vorrtex