WPF DataGrid删除IEditableCollectionView.CancelNew()上的NewItemPlaceholder

概观

我正在开发一个WPF应用程序(使用.NET 4.5),其中一部分涉及在DataGrid中显示一些数据。
用户可以在DataGrid中添加新行,并通过其他位置的按钮删除一行。

当用户开始添加无法提交的新行然后按下删除按钮时,我遇到了问题。
应取消新行,并将DataGrid重置为其先前的状态。
但是,DataGrid的NewItemPlaceholder行将被删除,并且不再显示。

我做了一个示例项目来演示这个问题。
这是一个简短的截屏video。
这就是示例应用程序的样子。

重现:

  1. 双击最上面一行的价格单元格
  2. 输入无效的数字以通过例外触发validation
  3. (可选)选择另一行
  4. 单击“删除”按钮

viewmodel获取ObservableCollection中的数据,ObservableCollection用作集合视图的源。 我有一个简单的命令连接到删除按钮。 如果用户正在添加项目( IEditableCollectionView.IsAddingNew ),我尝试在collectionView上使用.CancelNew()取消操作。 但是,当命令完成时,DataGrid NewItemPlaceholder删除其NewItemPlaceholder

到目前为止,我已经尝试过:

  • 触发DataGrid以通过设置dataGrid.CanUserAddRows = true再次显示占位符,这有点修复了问题,但这是一个可怕的解决方法并且它是错误的,之后占位符不可编辑。
  • 从源集合中删除无效项: this.productsObservable.Remove(this.Products.CurrentAddItem as Product)
    这不会改变行为,占位符仍然被删除。
  • 从集合视图中删除该项: this.Products.Remove(this.Products.CurrentAddItem)
    这会引发exception,这是有道理的: 'Remove' is not allowed during an AddNew or EditItem transaction.

有没有其他方法可以取消用户的添加并显示NewItemPlaceholder?

在示例项目中,为了简单起见,我在VM构造函数中实例化数据。
实际上我正在使用对服务的异步调用,将结果包装在ObservableCollection中,而ViewModel实现了INotifyPropertyChanged。 业务对象未实现INPC。

示例项目的XAML:

      

ViewModel,以及一个简单的业务对象:

 using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Windows.Data; using System.Windows.Input; namespace WpfApplication3 { public class ViewModel { private readonly ObservableCollection productsObservable; public ViewModel() { this.productsObservable = new ObservableCollection() { new Product() { Name = "White chocolate", Price = 1}, new Product() { Name = "Black chocolate", Price = 2}, new Product() { Name = "Hot chocolate", Price = 3}, }; this.Products = CollectionViewSource.GetDefaultView(this.productsObservable) as IEditableCollectionView; this.Products.NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtBeginning; this.DeleteCommand = new DelegateCommand(this.OnDeleteCommandExecuted); } public ICommand DeleteCommand { get; private set; } public IEditableCollectionView Products { get; private set; } private void OnDeleteCommandExecuted() { if (this.Products.IsAddingNew) { this.Products.CancelNew(); } } } public class Product { public string Name { get; set; } public decimal Price { get; set; } } } 

那这个呢:

 private void OnDeleteCommandExecuted() { if (this.Products.IsAddingNew) { this.Products.CancelNew(); this.Products.AddNew(); } } 

您仍将删除输入错误的行,但您将添加一个新的(大部分)空行。 唯一的问题,虽然我确定它的可修复性,是你在数值列中得到默认的0值而不是null