WPF DataGrid删除IEditableCollectionView.CancelNew()

时间:2015-04-23 16:51:52

标签: c# .net wpf mvvm datagrid

概述

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

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

我做了sample project来证明这个问题 Here也是一个简短的截屏视频 This是示例应用的样子。

重现:

  1. 双击最上面一行的价格单元格
  2. 输入无效的号码以通过例外触发验证
  3. (可选)选择另一行
  4. 点击删除按钮
  5. 代码

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

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

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

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

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

    示例项目的XAML:

    <Window x:Class="WpfApplication3.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:WpfApplication3"
            Title="MainWindow" Height="250">
        <Window.DataContext>
            <local:ViewModel />
        </Window.DataContext>
    
        <StackPanel Orientation="Vertical">
            <Button Command="{Binding DeleteCommand}" Content="Delete row" />
            <DataGrid
                ItemsSource="{Binding Products}"
                CanUserDeleteRows="False"
                CanUserAddRows="True"
                SelectionMode="Single">
            </DataGrid>
        </StackPanel>
    </Window>
    

    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<Product> productsObservable;
    
            public ViewModel()
            {
                this.productsObservable = new ObservableCollection<Product>()
                {
                    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; }
        }
    }  
    

1 个答案:

答案 0 :(得分:2)

这个怎么样:

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

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