【问题标题】:Wpf - How to control observable collection updatesWpf - 如何控制可观察的集合更新
【发布时间】:2015-12-18 15:55:01
【问题描述】:

在父级中有一个 Observable Collection PendingPayment,其中列出了所有待处理的销售付款以及已支付的列金额。

然后用户可以选择一个特定的销售并在新的子窗口中打开它。

如果用户只是在子窗口中编辑文本框支付金额并关闭窗口而不将新的支付金额保存到数据库,则出现问题的事情是父窗口中包含支付金额列的可观察集合被更新。

我想要的是仅当数据库中的值更新时才更新集合。

【问题讨论】:

  • 您需要创建一个单独的集合,其中包含不同的对象,以供子视图使用。然后在数据库保存完成后将数据复制回父可观察集合中的对象,或者在数据库保存后重新检索父表单中的数据。

标签: c# wpf collections observablecollection


【解决方案1】:

这可以通过在用户在列表中选择您的销售对象时创建一个副本来实现,然后将此副本用作您的子视图的视图模型。

只有在单击保存按钮并且数据库更新成功后,您才能在列表中的原始对象中设置新值。

如果您只需要编辑少数对象属性,另一种方法是创建和编辑对象并将其用作子窗口的视图模型。 像这样的:

public class Sale
{
    public int PaidAmount { get; set; }
    public int Some { get; set; }
    public int More { get; set; }
    public int Properties { get; set; }
}

public class SaleEditor
{
    private Sale _sale;

    public int PaidAmount { get; set; }

    public SaleEditor(Sale sale)
    {
        _sale = sale;
        PaidAmount = sale.PaidAmount;
    }

    public void Save()
    {
        // update your data here
        _sale.PaidAmount = PaidAmount;
    }
}

如果您需要原始对象来更新数据库,那么 save 方法可以先更新对象,如果数据库更新失败,则恢复更改:

    public void Save()
    {
        var oldAmount = _sale.PaidAmount;
        _sale.PaidAmount = PaidAmount;

        if (!SalesDB.Update(_sale))
            _sale.PaidAmount = oldAmount;
            // you could also read back the value from DB
    }

【讨论】:

    【解决方案2】:

    只要有可能(我从来没有看到它不能的原因),为了列出目的使用代理或扁平对象,您可以使用投影查询来实现这一点。然后用户从列表中选择一个项目,您唯一需要抓取的是一个键来加载完整对象及其所需的对象图,因为用例可能会要求。

    这是一个使用 Entity Framework 和 c# lambda 表达式的示例实现:

    使用匿名对象:

    var anonymousListProjection = DbContext.PendingPayments.Select( pp=> 
        new { pp.Order, pp.Amount})         
    


    使用硬编码代理:

    var hardcodedListProjection = DbContext.PendingPayments.Select( pp=> 
        new PendingPaymentProxy { Order = pp.Order, Amount = pp.Amount}) 
    
    //To return an observable:    
    var observableColl = new ObservableCollection<PendingPaymentProxy>
        (hardcodedListProjection.Tolist());
    
    public class PendingPaymentProxy 
    {
       public string Order { get; set; }
       public decimal Amount{ get; set; }    
    }
    

    除了避免因无意加载真实对象而可能导致的性能问题外,这样您只需要在用户保存在详细视图中时担心您的列表。

    【讨论】:

      猜你喜欢
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多