在过去的三天里,我一直面临着一个非常复杂的问题。我正在尝试订购应用程序,为此我想要一个包含MainCategory项目的ObservableCollection。现在,MainCategory项目包含一个CategoryName和另一个ObservableCollection菜肴。菜肴有这些道具:名称,价格和数量。我做了所有这些,绑定和一切都很完美。
问题出现在页面底部(ListView外部嵌套在Listview中)我想要一个带有TotalValue的TextBlock,每次需要更改菜肴的数量。我正在使用MVVM,我已经完成了对props和CollectionChanged的所有INotifyPropertyChanged,但这仅在我添加或删除某些内容时有效。当我在第二个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");
}
}
}
}
我只想找到一种方法,以便在Main observable集合中发生任何变化时保持我的总值更新,例如产品的数量。无论如何都要解雇CollectionChanged事件?
答案 0 :(得分:1)
如果在集合中的项目发生变化时需要更新,我会考虑不使用可观察集合。可观察集合仅用于在集合中添加或删除项目时注意。
我之前做过的事情与下面的代码相似。
在MainCategory
中,您只会公开IEnumerable<Dish>
而不是完整列表。然后,在MainCategory
中,您可以创建包装方法来添加和删除订阅属性更改通知的菜肴。然后,每当菜肴发生变化时,您都可以更新总计值,并通知您的菜肴列表已更改。
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 :(得分: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);
}
}
}