web-dev-qa-db-fra.com

Obtention du menu contextuel de la grille de données WPF Cliquez sur Ligne

J'ai un WPF DataGrid

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

J'ai le gestionnaire d'événements click en tant que: 

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

Comment puis-je obtenir la ligne sur laquelle se trouvait le menu contextuel avant le clic? L'objet sender est System.Windows.Controls.MenuItem, pas le DataGridRow. Comment puis-je obtenir la DataGridRow où le menu contextuel a été cliqué. (Je mets le DataGrid.ItemSource dans le code derrière le fichier.)

16
O.O.

Donc, en vous basant sur votre exemple de code, je suppose que vous liez votre DataGrid à un ObservableCollection d'objets dont vous liez les propriétés Site et Subject à DataGridColumns.

Pour l'essentiel, tout ce que vous avez à faire est de déterminer quel est l'élément lié au DataGridRow cliqué et de le supprimer de votre ObservableCollection. Voici un exemple de code pour vous aider à démarrer:

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);
}
27
dsfgsho

Généralement, vous ne traitez pas de lignes (si vous le faites - réfléchissez bien aux raisons), vous utilisez plutôt le modèle de vue. Lorsque vous ouvrez le menu contextuel, votre élément est sélectionné et accessible via la propriété DataGrid.SelectedItem. Cependant, si vous avez vraiment besoin de DataGridRow - vous avez votre DataGrid.SelectedIndex et il y a beaucoup de réponses ici SO sur la façon d'obtenir la ligne. like Obtenir une ligne dans une grille de données

6
morincer

Pour développer le point de morincer ci-dessus avec un exemple, je me suis retrouvé avec une approche plus simple ...

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

     _importViewModel.SourceList.Remove((SourceFileInfo)SourceDataGrid.SelectedItem);
 }

Dans mon cas, le

_importViewModel.SourceList 

observableCollection auquel les lignes sont liées. Donc, conformément aux meilleures pratiques, je supprime simplement l'élément sélectionné de la collection et la liaison prend en charge l'interface utilisateur. 

3
ebol2000

la réponse de dsfgsho a fonctionné pour moi, mais un clic droit sur une ligne de la grille ne la sélectionne pas automatiquement. Cela signifie que si votre objectif est ailleurs et que vous cliquez avec le bouton droit de la souris et sélectionnez un élément du menu contextuel, vous pouvez obtenir une exception en dehors de la plage définie pour item.SelectedCells [0], ou si vous avez sélectionné une ligne, puis cliquez avec le bouton droit rangée, vous pouvez obtenir des résultats inattendus.

J'ai traité cela en gérant "PreviewMouseRightButtonDown" sur la grille de données. Ici, je sélectionne explicitement une ligne lorsqu'elle est cliquée avec le bouton droit de la souris. J'oublie l'origine de ma classe UIHelpers (probablement ailleurs sur ce site - je l'utilisais pour résoudre les éléments de type glisser-déposer), mais cela devrait vous orienter dans la bonne direction si vous rencontrez ce problème. Ceci est une extension de la réponse acceptée:

// 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();
        }
    }
2
Elemental Pete

UIHelper de Pete élémentaire provient probablement de:

http://www.hardcodet.net/2009/03/moving-data-grid-rows-using-drag-and-drop

Cet article répertorie un zip qui contient UIHelper.cs. Ce n'est pas mon code, donc pas de copier/coller ici.

0
Patrick Artner