24

我有一个 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>

我有 click 事件处理程序:

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

如何获取单击之前上下文菜单所在的行?sender对象是,而System.Windows.Controls.MenuItem不是DataGridRow。如何获取DataGridRow单击上下文菜单的位置。(我DataGrid.ItemSource在文件后面的代码中设置了。)

4

6 回答 6

39

因此,根据您的示例代码,我假设您将 DataGrid 绑定到对象的 ObservableCollection,您将其属性 Site 和 Subject 绑定到 DataGridColumns。

本质上,您需要做的就是弄清楚绑定到单击的 DataGridRow 的项目是什么,并将其从 ObservableCollection 中删除。以下是一些示例代码,可帮助您入门:

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);
}
于 2013-05-29T21:40:29.863 回答
7

通常,您不处理行(如果您这样做 - 再次考虑原因) - 而是使用视图模型。当您打开上下文菜单时,您会选择您的项目,因此可以通过 DataGrid.SelectedItem 属性访问它。但是,如果你真的需要 DataGridRow - 你有你的 DataGrid.SelectedIndex 并且这里有很多关于如何获取行的答案。像在数据网格中获取行

于 2013-05-29T21:01:08.773 回答
4

为了用一个例子来扩展morincer的观点,我最终采用了一种更简单的方法......

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

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

就我而言,

_importViewModel.SourceList 

是行绑定到的 ObservableCollection。因此,根据最佳实践,我简单地从集合中删除选定的项目,并且绑定负责 UI。

于 2014-12-18T17:22:39.420 回答
2

dsfgsho 的答案对我有用,但右键单击网格行不会自动选择它。这意味着如果您的焦点在其他地方并且您右键单击并选择上下文菜单项,您可能会在 item.SelectedCells[0] 上获得超出范围的异常,或者如果您选择了一行并右键单击不同的行行,你可能会得到意想不到的结果。

我通过处理 Datagrid 上的“PreviewMouseRightButtonDown”来解决这个问题。在这里,我在右键单击时明确选择一行。我忘记了我的 UIHelpers 类是从哪里来的(可能在这个网站的其他地方——我用它来解决拖放项目),但是如果你遇到这个问题,这应该为你指明正确的方向。这是已接受答案的扩展:

// 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();
        }
    }
于 2015-05-15T15:07:19.947 回答
0

Elemental Pete 的 UIHelper 可能源于:

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

本文列出了一个包含 UIHelper.cs 的 Zip。这不是我的代码,所以这里没有复制/粘贴。

于 2017-08-22T06:18:24.103 回答
-1

dsfgsho接受的答案是有道理的,但是当将 CommandBinding 用于标准 ApplicationCommands 而不是显式 Click 事件时,它有点不同,因为发送者不是 MenuItem 而是 DataGrid 本身。

XAML:

<DataGrid.CommandBindings>
    <CommandBinding Command="Cut" CanExecute="DataGrid_CanCut" Executed="DataGrid_Cut" />
    <CommandBinding Command="Copy" CanExecute="DataGrid_CanCopy" Executed="DataGrid_Copy" />
    <CommandBinding Command="Paste" CanExecute="DataGrid_CanPaste" Executed="DataGrid_Paste" />
    <CommandBinding Command="New" CanExecute="DataGrid_CanAddNew" Executed="DataGrid_AddNew" />
    <CommandBinding Command="Delete" CanExecute="DataGrid_CanDelete" Executed="DataGrid_Delete" />
</DataGrid.CommandBindings>
<DataGrid.ContextMenu>
    <ContextMenu>
        <MenuItem Command="Cut" />
        <MenuItem Command="Copy" />
        <MenuItem Command="Paste" />
        <MenuItem Command="New" />
        <MenuItem Command="Delete" />
        <Separator />
        <MenuItem Header="Test" Command="{Binding CustomContextCommand}" />
    </ContextMenu>
</DataGrid.ContextMenu>

代码背后:

private void DataGrid_Delete(object sender, ExecutedRoutedEventArgs e)
{
    // Test whether cleared, resolved, etc., and confirm deletion
    var datagrid = (DataGrid)sender;
    var trans = (DataClasses.BankTransaction)datagrid.SelectedCells[0].Item;

    // Take action here; e.g., remove it from the underlying collection, remove it
    // from the DB, etc.

    e.Handled = true;
}

private void DataGrid_CanDelete(object sender, CanExecuteRoutedEventArgs e)
{
     e.CanExecute = true;
     e.Handled = true;
}
于 2020-02-05T20:13:17.503 回答