我有一个带有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?
要实现的目标:
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;
}
}
DataContext
)。我是WPF的新手,试图了解命令的工作原理。具体来说,此命令应采用IEnumerable<string>
的参数,或string
的集合。我已经完成并测试了deleteAction
方法。 string
对象将是DataGrid
所选行的“ ISBN”列中的值。您已经进入了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。
您的iBook听起来好像不是ViewModel。它应该是。您要绑定的几乎所有未明确标记为OneTime的东西都应该是实现inotifypropertychanged的viewmodel。这是因为存在一个长期存在的错误,否则可能会导致内存泄漏。不必担心您的视图模型是否会泄漏。只需始终使用一个viewmodel并构建一个实现inpc的基本viewmodel,以便您可以轻松地继承其中的所有内容。
最简单的解决方案是使用内置DataGrid.DeleteCommand
。
DataGrid
默认已支持行/单元格删除。通常,您无需自己创建一些复杂的东西。我会考虑浪费时间。
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选择所有行,然后按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>