删除 WPF DataGrid 中的选定项(多选)
Delete selected items in WPF DataGrid (multiselect)
我有一个带有 DataGrid
、菜单和按钮的 WPF 应用程序。选择 DataGrid
中的行时,将激活按钮和菜单项,以启用从数据库中删除数据的功能。
此主 window 的部分 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 将在 class 中定义,即上面主要 window 的 DataContext
。 class部分代码如下:
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?
要实现的目标:
- 选择
DataGrid
中的项目后,如果选择了一个或多个项目,删除命令的 UI 元素将被激活。这已经通过以下事件处理程序实现,在主要 window: 的代码隐藏中
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;
}
}
- 要执行的删除命令。目前尚不清楚的是如何将参数传递给在 ViewModel 中实现的命令(
DataContext
用于视图)。我是 WPF 的新手,正在尝试了解命令的工作原理。具体来说,此命令应采用 IEnumerable<string>
的参数,或者可能是 string
的集合。我已经完成并测试了 deleteAction
方法。 string
对象将是 DataGrid
. 的选定行的 "ISBN" 列中的值
您遇到了 wpf/mvvm 的棘手问题之一,因为无法绑定您理想中想要使用的内容。或者至少不是直接开箱即用。
如果您只想要一个项目 select 并删除,那么您可以将 selecteditem 绑定到 window 视图模型中的 属性。该命令可以使用提供的 IBook 对象进行删除。
由于您需要多个 selection 和删除,这很复杂,因为您无法绑定 selecteditems 的整个列表。这不是可绑定的依赖项 属性.
有很多方法可以解决这个问题。
您可以子 class 数据网格并扩展。
或
你可以使用行为。
这些允许您做的是封装一大块面向事件的代码并添加附加的依赖项 属性 来存储数据。这本身就是可绑定的。
我建议您阅读一般行为,并 google 稍微看一下示例。
绑定 selecteditems 是一个相当普遍的要求,您应该会得到很多点击。
不过这里有一个。
Select multiple items from a DataGrid in an MVVM WPF project
如果 IBook 可以在您的视图模型中使用,您最终会得到一个 observablecollection 列表。
我推荐 observablecollection,您可以在视图模型中订阅 collectionchanged 事件,以便查看计数。将 0 到 return false 用于您的命令的 CanExecute 和 1+ true.
您的 iBook 听起来不像是视图模型。
它应该是。
您要绑定的几乎所有未明确标记为 OneTime 的内容都应该是实现 inotify属性changed 的视图模型。这是因为存在一个长期存在的错误,否则会导致内存泄漏。不要担心你的视图模型是否会泄漏。只需始终使用视图模型并构建一个基本视图模型实现 inpc,这样您就可以轻松地从中继承所有内容。
最简单的解决方案是使用内置 DataGrid.DeleteCommand
.
DataGrid
默认已经支持row/cell删除。通常不需要自己创建复杂的东西。我会认为这是浪费时间。
DataGrid
公开了一个 static
DataGrid.DeleteCommand
,这是一个路由命令。 DataGrid
使用 CommandManager.RegisterClassCommandBinding
侦听此命令。
除了DataGrid.DeleteCommand
,还支持DataGrid.BeginEditCommand
(Key.F2
)、DataGrid.CommitEditCommand
、DataGrid.CancelEditCommand
(Key.Escape
)、DataGrid.SelectAllCommand
和 ApplicationCommands.Copy
.
你可以随时按CRTL + A到select所有行然后按DEL删除select编辑行。
如果要添加鼠标输入控制删除,需要在每一行添加一个删除按钮。这是最直观和最成熟的table设计。
这样做,要删除一行,用户不需要执行四个操作:首先导航到目标行,然后在该行上执行 select 行命令,然后第三次导航到删除按钮,最后按下删除按钮。用户现在可以直接按行的删除按钮。
这将删除两个操作以实现目标(删除一行)。在用户体验 (UX) 方面,必须使用尽可能少的用户操作和尽可能少的鼠标移动来实现目标。
Multiselect 删除仍然是可能的。用户必须 select 目标行,然后简单地按下随机删除按钮。 DataGrid
完成其余的工作,例如enable/disable 删除按钮。
以下示例使用 DataGridTemplateColumn
向每一行添加删除 Button
。该示例假定 table 两列,它们是自动生成的。通过将第三个删除按钮列的 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>
我有一个带有 DataGrid
、菜单和按钮的 WPF 应用程序。选择 DataGrid
中的行时,将激活按钮和菜单项,以启用从数据库中删除数据的功能。
此主 window 的部分 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 将在 class 中定义,即上面主要 window 的 DataContext
。 class部分代码如下:
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?
要实现的目标:
- 选择
DataGrid
中的项目后,如果选择了一个或多个项目,删除命令的 UI 元素将被激活。这已经通过以下事件处理程序实现,在主要 window: 的代码隐藏中
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;
}
}
- 要执行的删除命令。目前尚不清楚的是如何将参数传递给在 ViewModel 中实现的命令(
DataContext
用于视图)。我是 WPF 的新手,正在尝试了解命令的工作原理。具体来说,此命令应采用IEnumerable<string>
的参数,或者可能是string
的集合。我已经完成并测试了deleteAction
方法。string
对象将是DataGrid
. 的选定行的 "ISBN" 列中的值
您遇到了 wpf/mvvm 的棘手问题之一,因为无法绑定您理想中想要使用的内容。或者至少不是直接开箱即用。
如果您只想要一个项目 select 并删除,那么您可以将 selecteditem 绑定到 window 视图模型中的 属性。该命令可以使用提供的 IBook 对象进行删除。
由于您需要多个 selection 和删除,这很复杂,因为您无法绑定 selecteditems 的整个列表。这不是可绑定的依赖项 属性.
有很多方法可以解决这个问题。
您可以子 class 数据网格并扩展。
或
你可以使用行为。 这些允许您做的是封装一大块面向事件的代码并添加附加的依赖项 属性 来存储数据。这本身就是可绑定的。 我建议您阅读一般行为,并 google 稍微看一下示例。 绑定 selecteditems 是一个相当普遍的要求,您应该会得到很多点击。 不过这里有一个。
Select multiple items from a DataGrid in an MVVM WPF project
如果 IBook 可以在您的视图模型中使用,您最终会得到一个 observablecollection 列表。
我推荐 observablecollection,您可以在视图模型中订阅 collectionchanged 事件,以便查看计数。将 0 到 return false 用于您的命令的 CanExecute 和 1+ true.
您的 iBook 听起来不像是视图模型。 它应该是。 您要绑定的几乎所有未明确标记为 OneTime 的内容都应该是实现 inotify属性changed 的视图模型。这是因为存在一个长期存在的错误,否则会导致内存泄漏。不要担心你的视图模型是否会泄漏。只需始终使用视图模型并构建一个基本视图模型实现 inpc,这样您就可以轻松地从中继承所有内容。
最简单的解决方案是使用内置 DataGrid.DeleteCommand
.
DataGrid
默认已经支持row/cell删除。通常不需要自己创建复杂的东西。我会认为这是浪费时间。
DataGrid
公开了一个 static
DataGrid.DeleteCommand
,这是一个路由命令。 DataGrid
使用 CommandManager.RegisterClassCommandBinding
侦听此命令。
除了DataGrid.DeleteCommand
,还支持DataGrid.BeginEditCommand
(Key.F2
)、DataGrid.CommitEditCommand
、DataGrid.CancelEditCommand
(Key.Escape
)、DataGrid.SelectAllCommand
和 ApplicationCommands.Copy
.
你可以随时按CRTL + A到select所有行然后按DEL删除select编辑行。
如果要添加鼠标输入控制删除,需要在每一行添加一个删除按钮。这是最直观和最成熟的table设计。
这样做,要删除一行,用户不需要执行四个操作:首先导航到目标行,然后在该行上执行 select 行命令,然后第三次导航到删除按钮,最后按下删除按钮。用户现在可以直接按行的删除按钮。
这将删除两个操作以实现目标(删除一行)。在用户体验 (UX) 方面,必须使用尽可能少的用户操作和尽可能少的鼠标移动来实现目标。
Multiselect 删除仍然是可能的。用户必须 select 目标行,然后简单地按下随机删除按钮。 DataGrid
完成其余的工作,例如enable/disable 删除按钮。
以下示例使用 DataGridTemplateColumn
向每一行添加删除 Button
。该示例假定 table 两列,它们是自动生成的。通过将第三个删除按钮列的 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>