c# wpf wpfdatagrid wpf-4.0

c# - Obtención del menú contextual de la cuadrícula de datos de WPF Haga clic en Fila



wpfdatagrid wpf-4.0 (5)

Tengo un DataGrid WPF

<DataGrid AutoGenerateColumns="False" Name="dataGrid1" IsReadOnly="True" > <DataGrid.Columns> <DataGridTextColumn Header="Site" Binding="{Binding Site}" Width="150" /> <DataGridTextColumn Header="Subject" Binding="{Binding Subject}" Width="310" /> </DataGrid.Columns> <DataGrid.ContextMenu> <ContextMenu> <MenuItem Header="Delete" Click="Context_Delete"> <MenuItem.Icon> <Image Width="12" Height="12" Source="Images/Delete.png" /> </MenuItem.Icon> </MenuItem> </ContextMenu> </DataGrid.ContextMenu> </DataGrid>

Tengo el controlador de eventos de clic como:

private void Context_Delete(object sender, System.EventArgs e) { }

¿Cómo obtengo la fila en la que estaba el menú contextual antes del clic? El objeto sender es System.Windows.Controls.MenuItem , no el DataGridRow . ¿Cómo obtengo el DataGridRow donde se hizo clic en el menú contextual? (Establecí el DataGrid.ItemSource en el código detrás del archivo).


La respuesta de dsfgsho funcionó para mí, pero hacer clic con el botón derecho en una fila de la cuadrícula no la selecciona automáticamente. Esto significa que si su enfoque está en otra parte y hace clic con el botón derecho y selecciona un elemento del menú contextual, puede obtener una excepción de fuera de rango en el elemento.SelectedCells [0], o si tiene una fila seleccionada y haga clic derecho en otro fila, puede obtener resultados inesperados.

Traté esto manejando "PreviewMouseRightButtonDown" en el Datagrid. Aquí estoy seleccionando explícitamente una fila cuando se hace clic derecho. Olvidé de dónde provino mi clase de UIHelpers (probablemente en otra parte de este sitio, lo estaba usando para resolver elementos de arrastrar y soltar), pero esto debería apuntarle en la dirección correcta si tiene este problema. Esta es una extensión de la respuesta aceptada:

// handle right mouse click to select the correct item for context menu usage private void myDataGrid_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { //find the clicked row DataGridRow row = UIHelpers.TryFindFromPoint<DataGridRow>((UIElement) sender, e.GetPosition(myDataGrid)); if (row == null) { Debug.WriteLine("Row is null"); return; } else { Debug.WriteLine("Grid Row Index is " + row.GetIndex().ToString()); (sender as DataGrid).SelectedIndex = row.GetIndex(); } }


Para expandir el punto anterior de Morincer con un ejemplo, terminé con un enfoque más simple ...

private void MenuItem_OnClickRemoveSource(object sender, RoutedEventArgs e) { if (SourceDataGrid.SelectedItem == null) return; //safety first _importViewModel.SourceList.Remove((SourceFileInfo)SourceDataGrid.SelectedItem); }

En mi caso, la

_importViewModel.SourceList

Es la colección Observable a la que están vinculadas las filas. Por lo tanto, según las mejores prácticas, simplemente elimino el elemento seleccionado de la colección y el enlace se encarga de la interfaz de usuario.


Por lo general, no trata con filas (si lo hace, piense de nuevo sobre las razones), en lugar de eso, trabaja con el modelo de vista. Cuando abre el menú contextual, obtiene su elemento seleccionado, por lo que se puede acceder a él a través de la propiedad DataGrid.SelectedItem. Sin embargo, si realmente necesita DataGridRow, tiene su DataGrid.SelectedIndex y hay muchas respuestas aquí en SO sobre cómo obtener la fila. como obtener fila en datagrid


Por lo tanto, basándome en su código de ejemplo, supongo que enlaza su Cuadrícula de datos a una colección observable de los objetos de los cuales vincula las propiedades del sitio y el sujeto a las columnas de la columna de datos.

Básicamente, todo lo que debe hacer es averiguar cuál es el elemento vinculado al DataGridRow en el que se hizo clic y eliminarlo de su ObservableCollection. Aquí hay un código de ejemplo para empezar:

private void Context_Delete(object sender, RoutedEventArgs e) { //Get the clicked MenuItem var menuItem = (MenuItem)sender; //Get the ContextMenu to which the menuItem belongs var contextMenu = (ContextMenu)menuItem.Parent; //Find the placementTarget var item = (DataGrid)contextMenu.PlacementTarget; //Get the underlying item, that you cast to your object that is bound //to the DataGrid (and has subject and state as property) var toDeleteFromBindedList = (YourObject)item.SelectedCells[0].Item; //Remove the toDeleteFromBindedList object from your ObservableCollection yourObservableCollection.Remove(toDeleteFromBindedList); }