删除WPF DataGrid中的选定项目(多选)

问题描述 投票:1回答:2

我有一个带有DataGrid,菜单和按钮的WPF应用程序。选择DataGrid中的行时,将激活按钮和菜单项,以允许从数据库中删除数据。

此主窗口的部分XAML:

<Button ToolTip="Delete Record" Command="{Binding DeleteCommand}" Name="button_delete" IsEnabled="False"/>
<MenuItem>
    <MenuItem Header="Delete" IsEnabled="False" Name="menuItem_delete" Command="{Binding DeleteCommand}"/>
</MenuItem>

<DataGrid Name="BooksDataGrid" ItemsSource="{Binding BooksList}" SelectionChanged="dataGrid_selectionChanged">
    <DataGrid.Columns>
         <DataGridTextColumn Header="Title" Binding="{Binding title_long}"/>
         <DataGridTextColumn Header="ISBN" Binding="{Binding isbn}"/>
    </DataGrid.Columns>
</DataGrid>

DeleteCommand将在上面主窗口的DataContext类中定义。该类的部分代码如下:

sealed class BookViewModel
{
    public ObservableCollection<IBook> Books { get; private set; }

    // load data command code

    // delete record command code
    // ...
    public void deleteAction(IEnumerable<string> isbnList)
    {
        // delete data from database
        // this already works
    }
}

已经实现了从数据库加载数据的命令。该实现方式与以下问题的答案非常相似:How to bind WPF button to a command in ViewModelBase?

要实现的目标:

  1. [当选择DataGrid中的项目时,如果选择一项或多项,则激活用于删除命令的UI元素。这已经通过下面的事件处理程序实现了,该事件处理程序位于主窗口的代码背后:
private void dataGrid_selectionChanged(object sender, SelectionChangedEventArgs args)
{
    // this works

    // if nothing is selected, disable delete button and menu item
    if (BooksDataGrid.SelectedItems.Count == 0)
    {
         button_deleteBook.IsEnabled = false;
         menuItem_deleteBook.IsEnabled = false;
    }
    else
    {
        // delete command can now be executed, as shown in the binding in XAML
        button_deleteBook.IsEnabled = true;
        menuItem_deleteBook.IsEnabled = true;
    }
}
  1. 要执行的删除命令。到目前为止尚不清楚的是如何将参数传递给在ViewModel中实现的命令(对于View是DataContext)。我是WPF的新手,试图了解命令的工作原理。具体来说,此命令应采用IEnumerable<string>的参数,或string的集合。我已经完成并测试了deleteAction方法。 string对象将是DataGrid所选行的“ ISBN”列中的值。
c# .net wpf datagrid command
2个回答
0
投票
的部分XAML

您已经进入了wpf / mvvm的棘手问题之一,因为您理想中想要使用的内容无法绑定。或至少不能直截了当。

如果只想选择和删除一个项目,则可以将selecteditem绑定到窗口视图模型中的属性。该命令可以使用提供删除操作的IBook对象。

由于您要进行多次选择和删除,所以很麻烦,因为您无法绑定整个选定项目列表。这不是可绑定的依赖项属性。

有多种解决方法。

您可以细分数据网格并进行扩展。

您可以使用某种行为。这些操作使您可以封装大量面向事件的代码,并添加一个附加的依赖项属性来存储数据。然后,它本身可以绑定。我建议您通读一些一般的行为,然后用Google搜索一下示例。绑定selecteditems是一个相当普遍的要求,您应该获得许多成功。这是一个。

Select multiple items from a DataGrid in an MVVM WPF project

如果您可以在视图模型中使用IBook,则会得到一个observablecollection列表。

我建议使用observablecollection,您可以在视图模型中订阅collectionchanged事件,以便检查计数。使用0为命令的CanExecute返回false,而1+为true。

https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.icommand.canexecute?view=netcore-3.1#System_Windows_Input_ICommand_CanExecute_System_Object_

您的iBook听起来好像不是ViewModel。它应该是。您要绑定的几乎所有未明确标记为OneTime的东西都应该是实现inotifypropertychanged的viewmodel。这是因为存在一个长期存在的错误,否则可能会导致内存泄漏。不必担心您的视图模型是否会泄漏。只需始终使用一个viewmodel并构建一​​个实现inpc的基本viewmodel,以便您可以轻松地继承其中的所有内容。


0
投票

最简单的解决方案是使用内置DataGrid.DeleteCommand

DataGrid默认已支持行/单元格删除。通常,您无需自己创建一些复杂的东西。我会考虑浪费时间。

DataGrid显示static DataGrid.DeleteCommand,这是一个路由命令。 DataGrid使用CommandManager.RegisterClassCommandBinding收听此命令。除了DataGrid.DeleteCommand,还支持DataGrid.BeginEditCommandKey.F2),DataGrid.CommitEditCommandDataGrid.CancelEditCommandKey.Escape),DataGrid.SelectAllCommandApplicationCommands.Copy

您总是可以按CRTL + A选择所有行,然后按DEL删除所选的行。

如果要添加鼠标输入控制的删除,则应在每行添加一个删除按钮。这是最直观,最成熟的表格设计。这样做,要删除单个行,用户不需要执行四个操作:首先导航到目标行,然后在该行上执行select row命令,然后第三次导航到Delete按钮,最后按Delete按钮。用户现在可以直接按该行的删除按钮。为了完成目标,这删除了两个操作(删除一行)。就用户体验(UX)而言,必须使用尽可能少的用户操作和尽可能少的鼠标移动来实现目标。仍然可以进行多选删除。用户必须选择目标行,然后简单地按下随机删除按钮。 DataGrid执行其余操作,例如启用/禁用删除按钮。

以下示例使用Button向每行添加一个删除DataGridTemplateColumn。该示例假定一个两列的表是自动生成的。通过将第三删除按钮列的DataGridTemplateColumn.DisplayIndex设置为2,将该列定位在最右边。您可以使用DataGrid.FrozenColumnCount属性来阻止删除列滚动,即固定列,这将需要将删除列定位在最左侧。

<DataGrid AutoGenerateColumns="True">
  <DataGrid.Columns>
    <DataGridTemplateColumn DisplayIndex="2">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <Button Content="X" 
                  Command="{x:Static DataGrid.DeleteCommand}" />
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>
© www.soinside.com 2019 - 2024. All rights reserved.