Wpf - 如何控制可观察的集合更新

时间:2015-12-18 15:55:02

标签: c# wpf collections observablecollection

在母公司中有一个Observable Collection PendingPayment,其中列出了所有未付的销售付款,并且已支付了一列金额。

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

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

我想要的是只有在数据库中更新值时才能更新的集合。

2 个答案:

答案 0 :(得分: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
    }

答案 1 :(得分:1)

尽可能(我从未看到它为什么不能这样做),为了列出目的使用代理或平面对象,您可以使用投影查询来实现。然后,用户从列表中选择一个项目,您需要抓取的唯一内容是使用其必需的对象图加载完整对象的密钥,就像用例可能指示的那样。

以下是使用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; }    
}

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