简体   繁体   English

ObservableCollection内部的ObservableCollection不会触发Collection更改事件

[英]ObservableCollection inside ObservableCollection doen't fire Collection changed event

For the last three days I've been facing a quite a composite problem. 在过去的三天内,我一直面临一个非常复杂的问题。 I am trying to make an order taking app, to do this I wanted to have an ObservableCollection containing MainCategory items. 我正在尝试制作一个接受订单的应用程序,为此,我想拥有一个包含MainCategory项目的ObservableCollection。 Now the MainCategory items contained a CategoryName and another ObservableCollection of dishes. 现在MainCategory项目包含一个CategoryName和另一个菜式ObservableCollection。 The dishes have those props: name, price and quantity. 这些菜有那些道具:名称,价格和数量。 I did all this and the bindings and everything works perfectly. 我做了所有这些工作,绑定和所有工作都完美地进行了。

The problem is at the bottom of the page (outside the ListView which is nested inside a Listview ) I want to have a TextBlock with the TotalValue that needs to change every time The quantity of a dish changes. 问题出在页面底部(嵌套在Listview内的ListView之外),我想拥有一个TextBlock,它的TotalValue每次都需要改变。 I am using MVVM and I have done all the INotifyPropertyChanged to the props and the CollectionChanged, but this only works when I add or remove something. 我正在使用MVVM,并且已将所有INotifyPropertyChanged完成了对道具和CollectionChanged的操作,但这仅在我添加或删除内容时有效。 Not when I change the value of a prop in the second ObservableCollection. 当我在第二个ObservableCollection中更改prop的值时没有。

Here is some code: 这是一些代码:

    public class MenuCollection : ObservableCollection<MainCategories>,
INotifyCollectionChanged, INotifyPropertyChanged
{
    public MenuCollection()
    {
        Add(new MainCategories("Category1", false));
        this[0].SubMenuItems.Add(new Dishes("Dish1", 4));

    }
}

 public class MainCategories : MainViewModelBase
{

    public ObservableCollection<Dishes> SubMenuItems{get; set;}  
    public MainCategories(string name, bool visible)
    {
        this.categoryName = name;
        this.visible = visible;
        SubMenuItems = new ObservableCollection<Dishes>();
    }

    public string categoryName;
    public string CategoryName
    {
        get { return categoryName; }
        set
        {
            if (categoryName != value)
            {
                categoryName = value;
                OnPropertyChanged("CategoryName");
            }
        }
    }
    public bool visible;
    public bool Visible
    {
        get { return visible; }
        set
        {
            if (visible != value)
            {
                visible = value;
                OnPropertyChanged("Visible");
            }
        }
    }
}

public class Dishes : MainViewModelBase
{
    public Dishes(string dishName, int price)
    {
        this.dishName = dishName;
        this.dishPrice = price;
        this.quantity = 0;
    }

    private string dishName;
    public string DishName
    {
        get { return dishName; }
        set
        {
            if (dishName != value)
            {
                dishName = value;
                OnPropertyChanged("DishName");
            }
        }
    }
    private int dishPrice;
    public int DishPrice
    {
        get { return dishPrice; }
        set
        {
            if (dishPrice != value)
            {
                dishPrice = value;
                OnPropertyChanged("DishPrice");
            }
        }
    }
    private int quantity;
    public int Quantity
    {
        get { return quantity; }
        set
        {
            if (quantity != value)
            {
                quantity = value;
                OnPropertyChanged("Quantity");
            }
        }
    }

}

I just want to find a way to keep my total value update when anything changes inside the Main observable collection, like the quantity of a product. 我只想找到一种方法,可以在Main可观察集合内的任何变化(例如产品数量)发生变化时保持总价值更新。 is there anyway to fire the CollectionChanged event? 无论如何,有什么要触发CollectionChanged事件的?

this is the UI 这是UI 这是UI

and an earlier version without the buttons 和没有按钮的早期版本 和没有按钮的早期版本

I would consider possibly not using an observable collection if you need updates when items in the collection change. 如果集合中的项发生更改时需要更新,我会考虑不使用可观察的集合。 Observable collection is only useful for noting when items are added or removed from a collection. 可观察到的集合仅用于注意何时从集合中添加或删除项目。

Something that I've done before is similar to the code below. 我之前做过的事情与下面的代码相似。

In your MainCategory you would only expose an IEnumerable<Dish> instead of the full list. 在您的MainCategory您只会公开IEnumerable<Dish>而不是完整列表。 Then, in MainCategory you can create wrapping methods to add and remove dishes that subscribe to property changed notifications. 然后,在MainCategory您可以创建包装方法来添加和删除订阅属性更改通知的菜肴。 Then every time a dish changes you can make updates to your aggregate values like Total and notify that your list of dishes has changed. 然后,每次菜品更改时,您都可以更新总计(例如总计),并通知您菜品列表已更改。

private List<Dish> _subMenuItems = new List<Dish>();
public IEnumerable<Dish> SubMenuItems { get { return _subMenuItems; } }

public void AddDish(Dish dish)
{
    _subMenuItems.Add(dish);
    dish.PropertyChanged += dish_PropertyChanged;
    OnPropertyChanged("SubMenuItems");
}

public void RemoveDish(Dish dish)
{
    if (_subMenuItems.Contains(dish))
    {
        dish.PropertyChanged -= dish_PropertyChanged;
        _subMenuItems.Remove(dish);
        OnPropertyChanged("SubMenuItems");
    }
}

private double _total;
public double Total
{
    get { return _total; }
    set
    {
        if (_total != value)
        {
            _total = value;
            OnPropertyChanged("Total");
        }
    }
}

private void dish_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    Total = getTotal();
    // any other aggregate calculations can go here.
    OnPropertyChanged("SubMenuItems");
}

Another option that might work for you is something I picked up online a few years ago and is quite handy. 另一种可能对您有用的选择是几年前我在网上购买的,非常方便。 It is call a "Truly" observable collection and will fire events not only when items are added/removed but also when properties on the items within the list change. 它被称为“真正”的可观察集合,不仅会在添加/删除项目时触发事件,而且还会在列表中项目的属性发生更改时触发事件。 I havent tried it with a collection within a collection but it should work 我还没有在一个收藏夹中尝试过它,但是它应该可以工作

public sealed class TrulyObservableCollection<T> : ObservableCollection<T>
where T : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler ItemPropertyChanged;

    public TrulyObservableCollection()
        : base()
    {
        CollectionChanged += new NotifyCollectionChangedEventHandler(TrulyObservableCollection_CollectionChanged);
    }

    public TrulyObservableCollection(IEnumerable<T> pItems)
        : this()
    {
        foreach (var item in pItems)
        {
            this.Add(item);
        }
    }

    void TrulyObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (Object item in e.NewItems)
            {
                (item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }
        if (e.OldItems != null)
        {
            foreach (Object item in e.OldItems)
            {
                (item as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }
    }

    void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        NotifyCollectionChangedEventArgs a = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
        OnCollectionChanged(a);

        if (ItemPropertyChanged != null)
        {
            ItemPropertyChanged(sender, e);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM