2011-03-05 14 views
13

Tengo una cuadrícula de datos que potencialmente puede tener muchas filas. Como el usuario hace clic derecho en una de las filas, necesito mostrar un menú contextual para cada una de las filas y realizar una acción (misma acción pero diferente elemento de datos de acuerdo con la fila seleccionada actualmente) cuando el usuario hace clic en la opción.Crear contextmenus para las filas de la cuadrícula de datos

¿Cuál es la mejor estrategia para esto?

Temo que un ContextMenu para cada fila sea exagerado aunque estoy creando el menú usando el evento ContextMenuOpening, una especie de "carga lenta" para el menú contextual. ¿Debo usar solo un ContextMenu para la cuadrícula de datos? Pero con esto tendría algo más de trabajo con respecto al evento click, para determinar la fila correcta, etc.

Respuesta

29

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

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

+0

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

+0

@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

Cuestiones relacionadas