首页 > 解决方案 > 防止对一个窗口上的对象的更改影响另一个窗口

问题描述

在我的主窗口上,我有一个从 SQL 加载对象列表的数据网格:

if (PartView.Instance.CurrentPart != null)
{
    DgSupplierData.ItemsSource = partData.GetAllPartSuppliersByPart(PartView.Instance.CurrentPart.Id);
}

partData 只是一个帮助类,它使用 dapper 从存储过程中加载列表。

当用户双击一行时,会打开一个“编辑窗口”,这是一个将行数据分配给自定义对象 (PartSupplierModel) 以供用户编辑的基本窗口。一旦他们编辑了数据并点击了保存按钮,存储过程就会将数据保存到 SQL Server(非常简单并且工作正常)。但是,如果用户对任何文本框进行了任何更改,但随后决定他们不希望保存更改并且他们只是关闭表单然后重新选择同一行,则表单将保留他们所做的更改(尽管不会保存到 SQL Server,因为没有调用按钮事件,这是我们想要的)。我想要的是数据不会更改原始表中的源,除非单击了编辑/保存按钮。我相信这是由于我绑定对象的方式?然而,

示例:这显示了我如何在编辑表单上设置文本框

<TextBox x:Name="TxtManufacturer"
                     Text="{Binding Manufacturer, UpdateSourceTrigger=PropertyChanged}"
                     VerticalAlignment="Center"
                     Height="25"
                     MaxLength="150"/>

该对象在加载编辑表单时存储为成员变量,并设置为数据上下文:

private PartSupplierModel _partSupplier = new PartSupplierModel();

public PartSupplierView(PartSupplierModel supplierData = null, int partId = 0)
        {
            InitializeComponent();

            _partSupplier = supplierData;

            this.DataContext = _partSupplier;
        }

标签: c#sqlwpfdapper

解决方案


没有足够的信息来有效地回答这个问题,但我希望它能给出一些指示:

    private PartSupplierModel _partSupplier = new PartSupplierModel();

    public PartSupplierView(PartSupplierModel supplierData = null, int partId = 0)
    {
        InitializeComponent();

        _partSupplier = supplierData;

        this.DataContext = _partSupplier;
    }

没有*点说_partSupplier = new ...,因为您在构造函数中唯一要做的就是用传入的变量覆盖它,supplierData

这样做不会执行任何类型的克隆或复制,它只是意味着您在内存中的某个地方有一些对象,并且您将表单指向它

用户进行编辑,内存中的原始对象被更改,表单关闭但下一个保持更改。如果您打开一个新表单,它是否是新的并不重要,它会指向内存中原始更改的对象

你不妨写:

    public PartSupplierView(PartSupplierModel supplierData = null, int partId = 0)
    {
        InitializeComponent();

        this.DataContext = supplierData;
    }

这是否有助于您理解,如果您从不做取消真正用户所做更改的事情,或者如果您从不刷新传入 as 的对象supplierData,那么每次打开此表单时,它都会查看不断变化的更改对象

有很多方法可以解决这个问题,但通常归结为:

  • 如果用户取消或将其数据合并到“主”对象中,则处理副本并将其丢弃,否则将其保存到数据库中(数据库是主对象)
  • 在数据模型中构建一个工具,它跟踪原始值和更改的值,并在用户取消时将更改值恢复为原始值(每个属性由两个字段原始/当前支持。第一次创建时,两个字段都被写入但此后仅更新当前。两种接受/拒绝更改的方法用于将原始内容复制到当前(拒绝)或当前到原始内容(接受),具体取决于您要执行的操作。DataTable/DataRow 等数据容器执行此操作
  • 如果用户单击取消,则从数据库刷新对象 - 这与“处理副本”大致相同,因为数据库是事实的来源,而本地对象是非常临时的。这种方式使数据库的使用更加频繁

我们无法具体说明该怎么做,因为您的问题没有提供任何有关supplierData来源、存储方式、预期生命周期等信息。这就是您需要决定的;此表单正在编辑该对象,那么您要如何处理还原更改?再次获取对象/从其自身的本地副本或内部跟踪中恢复它并能够撤消?没有正确/错误的答案 - 这取决于系统的并发性和性能要求

*除非它有助于避免在 InitializeComponent 中由于 nullref 原因而导致崩溃,但我的观点是,制作一个新的它是无用的,因为你所做的就是扔掉新的并编辑原始数据


推荐阅读