2016-12-21 7 views
0

В течение последних трех дней я столкнулся с довольно сложной проблемой. Я пытаюсь сделать заказ с приложением, чтобы сделать это, я хотел иметь ObservableCollection, содержащий элементы MainCategory. Теперь элементы MainCategory содержали CategoryName и еще один ObservableCollection из блюд. У блюд есть те реквизиты: имя, цена и количество. Я сделал все это, и привязки, и все работает отлично.ObservableCollection внутри ObservableCollection doen't fire Collection измененное событие

Проблема находится в нижней части страницы (вне ListView, которая вложена внутри Listview). Я хочу иметь TextBlock с TotalValue, который должен меняться каждый раз. Количество блюда изменяется. Я использую MVVM, и я сделал все INotifyPropertyChanged для реквизита и CollectionChanged, но это работает только когда я добавляю или удаляю что-то. Не когда я изменяю значение опора во втором ObservableCollection.

Вот код:

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

} 

Я просто хочу, чтобы найти способ, чтобы сохранить мое полное обновление значения при каких-либо изменениях внутри главной наблюдаемой коллекции, как количество продукта. есть ли способ запустить событие CollectionChanged?

это UI this is the UI

и более ранняя версия без кнопок and an earlier version without the buttons

+2

* «когда-либо изменения внутри главной наблюдаемой коллекции, как и количество продукта. Есть в любом случае, чтобы запустить событие CollectionChanged» * То есть ничего не нужно делать с 'CollectionChanged'. Это 'INotifyPropertyChanged'. У вас есть уродливая проблема. 'MainCategories' должен обрабатывать' PropertyChanged' на всех '' Dishes'' в своей коллекции. Когда свойство, подлежащее суммированию, изменяется, 'MainCategories' пересчитывает сумму и присваивает это свойство, возможно,' MainCategories.Sum'. 'MenuCollection' делает то же самое с свойствами' Sum' своих элементов. XAML привязывается к MainCollection.Sum –

ответ

1

я считал бы, возможно, не используя наблюдаемые коллекции, если вам нужно обновление, когда элементы в изменении коллекции. Наблюдаемая коллекция полезна только для того, чтобы отметить, когда элементы добавляются или удаляются из коллекции.

Что-то, что я делал раньше, похоже на приведенный ниже код.

В вашем MainCategory вы бы указали только IEnumerable<Dish>, а не полный список. Затем в MainCategory вы можете создавать методы обертывания для добавления и удаления блюд, которые подписываются на измененные уведомления об изменении свойств. Затем каждый раз, когда меняется блюдо, вы можете обновлять свои совокупные значения, например Total, и уведомлять, что ваш список блюд изменился.

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"); 
} 
1

Еще один вариант, который может сработать для вас, - это то, что я взял в Интернете несколько лет назад и весьма удобен. Он вызывает «истинно» наблюдаемую коллекцию и будет запускать события не только при добавлении/удалении элементов, но также при изменении свойств элементов в списке. Я попытался нету его коллекцию в коллекции, но он должен работать

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