wpf ObservableCollection.CollectionChanged 不触发
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15698195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ObservableCollection.CollectionChanged not firing
提问by Edwin
I have the following interface:
我有以下界面:


When an item is added into the DataGrid, the Total columnwill update according to (price * quantity), and the total TextBoxwill also have the total of all the rows added.
当一个项目被添加到 中时DataGrid,Total column将根据(价格 * 数量)更新,并且总数TextBox也会有添加的所有行的总数。
However, when I change the quantity of a row, the Total columnupdates, but the total TextBoxdoes not.
但是,当我更改一行的数量时,会Total column更新,但总数TextBox不会。
Here is my code, thanks in advance.
这是我的代码,提前致谢。
public partial class pgCheckout : Page {
ObservableCollection<SaleItem> items = new ObservableCollection<SaleItem>();
public pgCheckout() {
InitializeComponent();
dgItems.ItemsSource = items;
dgItems.Loaded += SetMinWidths;
items.CollectionChanged += setTotal;
}
public void setTotal(object source, EventArgs e) {
decimal total = 0;
foreach(SaleItem i in items) {
total += i.Total;
}
txtTotal.Text = total.ToString();
}
public void SetMinWidths(object source, EventArgs e) {
foreach (var column in dgItems.Columns) {
if (column.DisplayIndex != 0) {
column.MinWidth = column.ActualWidth;
column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
}
}
}
private void btnRemove_Click(object sender, RoutedEventArgs e) {
items.RemoveAt(dgItems.SelectedIndex);
}
private void btnAdd_Click(object sender, RoutedEventArgs e) {
bool exist = false;
foreach (SaleItem i in items) {
if (i.ItemID.Equals(txtItemID.Text))
exist = true;
}
if (exist) {
lblErr.Content = "Item already exist";
txtItemID.Text = "";
}
else {
using (var db = new PoSEntities()) {
var query = from i in db.Items
where i.ItemID.Equals(txtItemID.Text.Trim())
select i;
var itm = query.FirstOrDefault();
if (itm == null) {
lblErr.Content = "Invalid Item";
txtItemID.Text = "";
}
else {
txtItemID.Text = "";
lblErr.Content = "";
items.Add(new SaleItem() {
Num = items.Count + 1,
ItemID = itm.ItemID,
Name = itm.Name,
Price = decimal.Round(itm.Price, 2, MidpointRounding.AwayFromZero),
Quantity = 1,
});
}
}
}
}
private void txtItemID_KeyUp(object sender, KeyEventArgs e) {
if (e.Key == System.Windows.Input.Key.Enter) {
btnAdd_Click(txtItemID, e);
}
}
}
class SaleItem : INotifyPropertyChanged {
public int Num { get; set; }
public string ItemID { get; set; }
public string Name { get; set; }
private decimal price;
public decimal Price {
get { return price; }
set {
this.price = value;
OnPropertyChanged("Total");
}
}
public int quantity;
public int Quantity {
get { return quantity; }
set {
this.quantity = value;
OnPropertyChanged("Total");
}
}
public decimal Total {
get { return decimal.Round(Price * Quantity, 2, MidpointRounding.AwayFromZero); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
回答by Hossein Narimani Rad
ObservableCollection.CollectionChangedfire when something is added or deleted from the collection not the individual members being update.
ObservableCollection.CollectionChanged当从集合中添加或删除某些内容而不是正在更新的单个成员时触发。
...
else
{
txtItemID.Text = "";
lblErr.Content = "";
SaleItem newItem = new SaleItem() {
Num = items.Count + 1,
ItemID = itm.ItemID,
Name = itm.Name,
Price = decimal.Round(itm.Price, 2, MidpointRounding.AwayFromZero),
Quantity = 1 };
newItem.PropertyChanged +=
new PropertyChangedEventHandler(newSaleItem_PropertyChanged);
items.Add(newItem);
}
...
And this is the newSaleItem_PropertyChanged:
这是newSaleItem_PropertyChanged:
void newSaleItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
setTotal(null, null);
}
回答by Nahum
ObservableCollection<SaleItem> items = new ObservableCollection<SaleItem>();
must be a propery
必须是财产
change it to
将其更改为
public ObservableCollection<SaleItem> items {get;set;}
and do the new in the constructor
并在构造函数中做新的
or make the get function create new object if one doesn't exist
或者如果不存在则让 get 函数创建新对象
you must have public getter/setter to use binding
你必须有公共 getter/setter 才能使用绑定
回答by Dilshod
Your SaleItemmust implement INotifyPropertyChangedthen you will have PropertyChangedevent and you can subscribe to it. Using INotifyPropertyChanged will be good for binding.
您SaleItem必须实现INotifyPropertyChanged然后您将有PropertyChanged事件并且您可以订阅它。使用 INotifyPropertyChanged 将有利于绑定。

