C# WPF DataGrid正在删除IEditableCollectionView.CancelNew()上的NewItemPlaceholder 概述

C# WPF DataGrid正在删除IEditableCollectionView.CancelNew()上的NewItemPlaceholder 概述,c#,.net,wpf,mvvm,datagrid,C#,.net,Wpf,Mvvm,Datagrid,我正在开发一个WPF应用程序(使用.NET4.5),其中一部分涉及在DataGrid中显示一些数据。 用户可以在DataGrid中添加新行,并通过其他地方的按钮删除一行 当用户开始添加无法提交的新行,然后按下删除按钮时,我遇到问题。 应取消新行,并将DataGrid重置为其以前的状态。 但是,DataGrid的NewItemPlaceholder行被删除,不再显示 我已经做了一个演示,说明了这个问题。 这也是一个简短的放映。 是示例应用程序的外观 复制: 双击最上面一行的价格单元格 输入无效数字

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

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

我已经做了一个演示,说明了这个问题。
这也是一个简短的放映。
是示例应用程序的外观

复制:

  • 双击最上面一行的价格单元格
  • 输入无效数字以通过异常触发验证
  • (可选)选择另一行
  • 单击删除按钮
  • 代码 viewmodel获取ObservableCollection中的数据,ObservableCollection用作collection视图的源。 我有一个简单的命令连接到删除按钮。如果用户正在添加项目(
    IEditableCollectionView.IsAddingNew
    ),我将尝试使用collectionView上的
    .CancelNew()
    取消该操作。但是,当命令完成时,DataGrid将删除其
    NewItemPlaceholder

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

    • 要使占位符再次显示,请设置
      dataGrid.CanUserAddRows=true
      ,这在一定程度上解决了此问题,但这是一个可怕的解决方法,而且存在缺陷,之后占位符将不可编辑
    • 正在从源集合中删除无效项:
      this.productsBServable.Remove(this.Products.CurrentAddItem as Product)

      这不会改变行为,占位符仍然被删除
    • 从集合视图中删除项目:
      this.Products.Remove(this.Products.CurrentAddItem)

      这会引发一个异常,这很有意义:
      在AddNew或EditItem事务期间不允许“删除”。
    是否有其他方法可以取消用户的添加并显示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; }
        }
    }  
    
    使用系统;
    使用System.Collections.ObjectModel;
    使用系统组件模型;
    使用System.Linq;
    使用System.Windows.Data;
    使用System.Windows.Input;
    命名空间WpfApplication3
    {
    公共类视图模型
    {
    私有只读可观察收集产品可服务;
    公共视图模型()
    {
    this.productsObservable=新的ObservableCollection()
    {
    新产品(){Name=“白巧克力”,价格=1},
    新产品(){Name=“黑巧克力”,价格=2},
    新产品(){Name=“热巧克力”,价格=3},
    };
    this.Products=CollectionViewSource.GetDefaultView(this.productsBServable)作为IEditableCollectionView;
    this.Products.newItemPlaceholder Position=newItemPlaceholder Position.atStart;
    this.DeleteCommand=新的DelegateCommand(执行了this.ondeletecommand);
    }
    公共ICommand DeleteCommand{get;private set;}
    公共IEditableCollectionView产品{get;private set;}
    私有void OnDeleteCommandExecuted()
    {
    如果(此.Products.IsAddingNew)
    {
    this.Products.CancelNew();
    }
    }
    }
    公共类产品
    {
    公共字符串名称{get;set;}
    公共十进制价格{get;set;}
    }
    }  
    
    这个怎么办:

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

    您仍然会删除输入错误的行,但会添加一个新的(大部分)空行。唯一的问题是,尽管我确信它是可以解决的,但是您在数字列中得到了默认的
    0
    值,而不是
    null

    谢谢,我也尝试过这个方法。它看起来还可以(除了必须解决零问题外),但问题是,当您在之后双击新行时,新行不会进入编辑模式。知道为什么吗?@Stanislav问题是在
    之后。AddNew()
    ,则
    NewItemPlaceHolder
    不再是
    DataGrid
    中的最后一行。它仍然存在于可视树中,但不再可见。您解决问题了吗?因为我有相同的问题issue@Jamaxack我换成了Telerik RadGridView,因为那是我当时的选择。如果有帮助的话,也可以看看这个(我只是不记得它是否和这篇文章是同一个问题,但我记得它是相关的):。