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

WPF DataGrid复制行后TextBox绑定源联动异常问题

问题原因

你当前的复制逻辑存在两个问题,直接导致重复行绑定联动:

  • 插入集合时直接传入了原TransactionItem对象的引用,集合中两个条目指向内存中同一个对象实例,双向绑定修改任意一个条目对应对象的属性,自然会同步反映到所有指向该实例的行上。
  • 代码直接修改了原对象的ID属性,会覆盖被复制行原本的ID值,属于逻辑错误。
修复方案

核心逻辑是插入新行前必须创建独立的TransactionItem实例,将原对象的属性值拷贝到新实例后,再把新实例插入集合,禁止直接插入原对象引用。

方案1:手动属性拷贝(最稳妥,推荐属性较少时使用)

直接修正后台点击事件代码即可:

private void DuplicateItem_Click(object sender, RoutedEventArgs e){
    TransactionItem originalItem = ((FrameworkElement)sender).DataContext as TransactionItem;
    if (originalItem == null) return;

    // 创建独立的新对象实例
    TransactionItem newItem = new TransactionItem
    {
        // 给新对象分配独立ID,不要修改原对象的ID
        ID = transactionViewModel.TransactionDataGridItems.Count + 1,
        // 逐行拷贝原对象的所有业务属性值
        Amount = originalItem.Amount,
        // 按照你的TransactionItem定义,补充其他需要复制的属性,例如:
        // Remark = originalItem.Remark,
        // TransactionTime = originalItem.TransactionTime,
        // Category = originalItem.Category
    };

    int insertIndex = transactionViewModel.TransactionDataGridItems.IndexOf(originalItem) + 1;
    transactionViewModel.TransactionDataGridItems.Insert(insertIndex, newItem); 
}

方案2:对象克隆(适合属性较多的场景)

如果TransactionItem属性较多,手动赋值过于繁琐,可以给实体类增加克隆方法:

public class TransactionItem
{
    public int ID { get; set; }
    public decimal Amount { get; set; }
    // 其他属性定义...

    /// <summary>
    /// 创建当前对象的副本
    /// </summary>
    public TransactionItem Clone()
    {
        // 仅包含值类型属性时,MemberwiseClone即可满足需求
        TransactionItem clonedItem = (TransactionItem)this.MemberwiseClone();
        // 如果类中包含引用类型属性(比如自定义类、集合等),需要在这里单独为引用类型属性创建新实例,避免嵌套引用共用
        // 例如:clonedItem.Tags = new List<Tag>(this.Tags);
        return clonedItem;
    }
}

对应点击事件可以简化为:

private void DuplicateItem_Click(object sender, RoutedEventArgs e){
    TransactionItem originalItem = ((FrameworkElement)sender).DataContext as TransactionItem;
    if (originalItem == null) return;

    TransactionItem newItem = originalItem.Clone();
    newItem.ID = transactionViewModel.TransactionDataGridItems.Count + 1;

    int insertIndex = transactionViewModel.TransactionDataGridItems.IndexOf(originalItem) + 1;
    transactionViewModel.TransactionDataGridItems.Insert(insertIndex, newItem); 
}
注意事项
  • 如果实体包含引用类型成员,必须对引用类型成员也做独立拷贝(即深拷贝),否则嵌套属性依然会出现多行星级联动的问题。
  • 所有针对新行的属性修改(比如分配新ID),都要作用在新创建的副本对象上,不要改动原对象的属性值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 13:54:23