You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF DataGrid启用CanUserAddRows时如何添加指定子类对象

解决WPF DataGrid新增行创建指定子类实例的问题

有两种可靠的方法可以让DataGrid新增行时创建你需要的WorkItem子类实例,同时让WorkItem可以保持为抽象类:

方法1:处理DataGrid的AddingNewItem事件

这是最直接的方案,直接拦截DataGrid的新增行为,替换默认创建的实例:

步骤1:在XAML中绑定事件

给你的DataGrid添加AddingNewItem事件处理:

<DataGrid x:Name="MasterDataGrid"
          ItemsSource="{Binding WorkItems}"
          CanUserAddRows="True"
          AddingNewItem="MasterDataGrid_AddingNewItem">
    <!-- 你的列定义 -->
</DataGrid>

步骤2:在后台代码中替换实例

在事件处理方法中,将默认创建的WorkItem替换为目标子类(比如Article):

private void MasterDataGrid_AddingNewItem(object sender, AddingNewItemEventArgs e)
{
    // 直接赋值为你需要的子类实例
    e.NewItem = new Article();
}

优点:实现简单,无需修改集合类型,适合单个DataGrid的场景。
注意:如果采用MVVM模式,可以通过命令或行为将事件逻辑移到ViewModel中,避免后台代码耦合。

方法2:自定义类型化ObservableCollection

如果需要在多个地方复用这个逻辑,可以创建一个自定义集合类,统一管理新增实例的类型:

实现自定义集合

public abstract class WorkItem : INotifyPropertyChanged
{
    // 你的抽象类实现,包含INotifyPropertyChanged逻辑
    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Article : WorkItem
{
    // 你的Article子类实现
}

public class TypedObservableCollection<TBase, TDerived> : ObservableCollection<TBase>
    where TDerived : TBase, new()
{
    public TypedObservableCollection()
    {
        // 获取集合视图并绑定新增事件
        var collectionView = CollectionViewSource.GetDefaultView(this) as IEditableCollectionView;
        collectionView?.AddingNew += (s, e) => e.NewItem = new TDerived();
    }
}

在ViewModel中使用

public class MD_ArticleViewModel
{
    public TypedObservableCollection<WorkItem, Article> WorkItems { get; } 
        = new TypedObservableCollection<WorkItem, Article>();
    
    // 其他ViewModel逻辑
}

绑定到DataGrid

直接将DataGrid的ItemsSource绑定到这个自定义集合,开启CanUserAddRows="True"即可,新增行时会自动创建Article实例。

优点:逻辑复用性强,适合多个控件需要相同新增行为的场景;完全符合MVVM模式,无需后台代码。

解决的核心问题

  1. WorkItem可设为抽象类:两种方法都不需要实例化WorkItem,新增的是具体子类,因此可以放心将WorkItem定义为抽象类。
  2. 新增对象为目标子类:后续对集合的操作中,新增的实例都是Article(或其他子类)类型,无需额外类型转换即可正常处理。

内容的提问来源于stack exchange,提问作者Rikube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:50:07