【问题标题】:Prevent changes to an object on one window affecting another防止对一个窗口上的对象的更改影响另一个窗口
【发布时间】:2021-08-04 04:26:20
【问题描述】:

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

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

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

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

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

<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;
        }

【问题讨论】:

  • public PartSupplierView() 是表单的构造函数,在使用“new”时仅调用一次。如果您创建一个 Load() 方法并放入以下行: this.DataContext = _partSupplier;那么每次使用 Show() 方法时,DGV 都会加载原始数据。

标签: c# sql wpf dapper


【解决方案1】:

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

    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;
    }

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2012-05-04
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多