ObservableCollection CollectionChanged 在 WPF MVVM 中没有帮助

Posted

技术标签:

【中文标题】ObservableCollection CollectionChanged 在 WPF MVVM 中没有帮助【英文标题】:ObservableCollection CollectionChanged not helpful in WPF MVVM 【发布时间】:2012-04-23 18:01:36 【问题描述】:

我正在使用 DataGrid,并使用 ViewModel 中的 ObservableCollection 进行绑定

private ObservableCollection<StockItem> _stockList;
public ObservableCollection<StockItem> StockList

    get
    
        return _stockList;
    
    set
    
        _stockList = value;
        OnPropertyChanged("StockList");                
    

StockItem 类包含其属性,即 DataGrid 中的列。 DataGrid中有一个名为Amount的列,其值随同一个datagrid的Quantity*Price列发生变化。

我在 ViewModel 中有一个名为 TotalAmount 的属性,它是在 ObservableCollection CollectionChanged 事件中计算的,例如

void OnStockListChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)

    this.TotalAmount = this.StockList.Sum(t => t.Amount);

只有在将新行添加到包含一些数据的 DataGrid 时,才会在绑定到 TotalAmount 的 TextBox 中更新此值。我希望在数据网格中的金额列更改后立即更新 TotalAmount 的这个 TextBox。

我该怎么做。

StockItem Class

public class StockItem : ObservableObject, ISequencedObject

    JIMSEntities dbContext = new JIMSEntities();
    public StockItem()
    
        var qs = dbContext.Stocks.Select(s => s.StockName);
        _stocks = new CollectionView(qs.ToArray());
        _stocks.CurrentChanged += new EventHandler(Stocks_CurrentChanged);
    
    void Stocks_CurrentChanged(object sender, EventArgs e)
    
        if (_stocks.CurrentItem != null)
            StockName = _stocks.CurrentItem.ToString();
        var qs = (from p in dbContext.Stocks
                  where p.StockName.Contains(StockName)
                  select new  Unit = p.Unit, UnitPrice = p.UnitPrice ).SingleOrDefault();
        if (qs != null)
        
            Unit = qs.Unit;
            UnitPrice = (decimal)qs.UnitPrice;
        
    

    private CollectionView _stocks;
    public CollectionView Stocks
    
        get
        
            return _stocks;
        
        set
        
            _stocks = value;
            OnPropertyChanged("Stocks");
        
    
    private int _sNo;
    public int SNo
    
        get
        
            return _sNo;
        
        set
        
            _sNo = value;
            OnPropertyChanged("SNo");

        
    
    private string _stockName;
    public string StockName
    
        get
        
            return _stockName;
        
        set
        
            _stockName = value;
            OnPropertyChanged("StockName");
        
    
    private decimal _unitPrice;
    public decimal UnitPrice
    
        get
        
            return _unitPrice;
        
        set
        
            _unitPrice = value;
            OnPropertyChanged("UnitPrice");
            OnPropertyChanged("Amount");
        
    
    private string _unit;
    public string Unit
    
        get
        
            return _unit;
        
        set
        
            _unit = value;
            OnPropertyChanged("Unit");
        
    

    private decimal _discount;
    public decimal Discount
    
        get
        
            return _discount;
        
        set
        
            _discount = value;
            OnPropertyChanged("Discount");
            OnPropertyChanged("Amount");
        
    
    private decimal _quantity;
    public decimal Quantity
    
        get
        
            return _quantity;

        
        set
        
            _quantity = value;
            OnPropertyChanged("Quantity");
            OnPropertyChanged("Amount");
        
    
    public decimal Amount
    
        get
        
            decimal total = Quantity * (UnitPrice - (UnitPrice * (Discount / 100)));
            return total;
        
            

    public override string ToString()
    
        return StockName;
    

【问题讨论】:

您的 StockItem 类是否实现了 INotifyPropertyChanged? 使用ObservableCollection that also monitors changes on the elements in collection。 是的,它实现了 INotifyPropertyChanged TotalAmount 长什么样子? 【参考方案1】:

所以,基本上,您所看到的是由于对ObservableCollection 的常见误解。 OC 在其包含的对象发生更改时不会通知。它会在 IT 更改时发出通知(查看 INotifyCollectionChanged)——添加、删除项目等时。

当包含在 OC 中的 StockItem 发生更改时,您想要做的是得到通知。你将不得不做几件事

1) 确保 INotifyPropertyChanged(你说你已经在做)在你的 StockItem 上实现了 2) 自定义或查找ObservableCollection 的实现,当集合中包含的项目发生更改时通知 (here is one)

【讨论】:

谢谢老兄,那个链接帮助了我。尽管我之前在 *** 中看到过该类,但现在我在我的代码中实现了它 我知道这是在复活一个非常古老的话题,但您是否碰巧将代码包含在“这里有一个”链接中?该网站现已关闭,我仍然很想效仿这个例子。谢谢。 here is one 所指向的链接现在只指向一个简单的“pageok”页面。【参考方案2】:

您需要订阅集合中所有项目的PropertyChanged,以便在任何项目上的Amount 更改时也重新计算值,这有点混乱。某个地方的某个人可能为此编写了实用程序类...

【讨论】:

以上是关于ObservableCollection CollectionChanged 在 WPF MVVM 中没有帮助的主要内容,如果未能解决你的问题,请参考以下文章

Listview 双向绑定与 ObservableCollection

如何将标签的 ItemsControl 绑定到 ObservableCollection

WPF ObservableCollection 异步调用问题

Xamarin 表单:分组 ObservableCollection

合并的 ObservableCollection

为啥在 DataGrid 中刷新 ObservableCollection 很慢