【问题标题】:How to fire INotifyPropertyChanged on a read-only property that uses nested properties to calculate a value如何在使用嵌套属性计算值的只读属性上触发 INotifyPropertyChanged
【发布时间】:2014-01-21 10:56:37
【问题描述】:

我的问题与INotifyPropertyChanged and calculated property类似

我重用了上面示例中的一些代码,因为这样更容易理解发生了什么。

假设我从类似的东西开始。请注意,INotifyPropertyChangedBase 是我用来实现 INotifyPropertyChanged 的​​基类。

public class Order : INotifyPropertyChangedBase
{
  private string itemName;
  public string ItemName 
  { 
    get { return itemName; }
    set 
    {
       itemName = value;
    }
  }

  private decimal itemPrice;
  public decimal ItemPrice 
  { 
    get { return itemPrice; }
    set 
    {
       itemPrice = value;
    }
  }

  private int quantity;
  public int Quantity 
  { 
    get { return quantity; }
    set 
    {
       quantity= value;
       OnPropertyChanged("Quantity");
       OnPropertyChanged("TotalPrice");
    }
  }

  public decimal TotalPrice
  {
    get { return ItemPrice * Quantity; }    
  }
}

在生成与此类似的代码后,我意识到每个订单可能由多个Items 组成,因此我生成了一个类似于此的class : Item

public class Item : INotifyPropertyChangedBase
{
  private string name;
  public string Name
  {
    get { return name; }
    set { name = value; }
  }

  private decimal price;
  public decimal Price
  {
    get { return price; }
    set { price = value; }
  }

  private int quantity;
  public int Quantity
  {
    get { return quantity; }
    set
    { 
      quantity = value;
      OnPropertyChanged("Quantity");
    }
  }
}

然后我将我的 Order 类转换为如下所示。

public class Order : INotifyPropertyChangedBase
{
  private ObservableCollection<Item> itemInfo;
  public ObservableCollection<Item> ItemInfo 
  { 
    get { return itemInfo; }
    set 
    {
       itemInfo = value;
       OnPropertyChanged("ItemInfo");
       OnPropertyChanged("TotalPrice");
    }
  }

  public decimal TotalPrice
  {
    get 
    { 
      Decimal totalPrice;
      foreach (Item item in ItemInfo)
      {
        totalPrice += item.Quantity * item.Price;
      }
      return totalPrice;
    }    
  }
}

通过DataGrid 实现这一点。每个Order 是一行。我将列标题绑定到Item.Name(选项数量有限)和Item.Quantity 到相应的列单元格。最后一列是TotalPrice

以前,当我更改 Quantity 时,TotalPrice 会更新。现在,在使用Item 的新实现中,TotalPrice 将不会在DataGrid 中更新。当我更新Item.Quantity 的实例时,ItemInfo 的设置器似乎不会触发。当我更新适当的DataGrid 单元格时,Item.Quantity 上的设置器会触发。

如何获取只读属性 (TotalPrice) 的值以使用嵌套属性 (Item) 进行更新?

【问题讨论】:

  • 为要添加到 ItemInfo 中的每个项目挂钩 PropertyChanged 事件。像 item1.PropertyChanged += item_PropertyChanged。在那个 item_PropertyChanged 处理程序中检查 e.PropertyName=="Quantity" 并 Raise OnPropertyChanged("TotalPrice");在那个条件检查中。
  • 您能否提供更多细节。可能把这个放在答案中?我在实施下面的潜在解决方案时遇到了问题。

标签: c# wpf binding datagrid inotifypropertychanged


【解决方案1】:

你将不得不听 ItemInfo 的 CollectionChanged 之类的

public class Order : INotifyPropertyChangedBase
{
   public Order()
   {  
    ItemInfo =new ObservableCollection<Item>();
    ItemInfo.CollectionChanged += ItemInfo_CollectionChanged;

    }

void ItemInfo_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        OnPropertyChanged("TotalPrice");
    }

   private ObservableCollection<Item> itemInfo;
   public ObservableCollection<Item> ItemInfo 
   { 
     get { return itemInfo; }
     set 
     {
         itemInfo = value;
         OnPropertyChanged("ItemInfo");
         OnPropertyChanged("TotalPrice");
}

}

public class Order : INotifyPropertyChangedBase
{

void ItemInfo_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        OnPropertyChanged("TotalPrice");
    }

   private ObservableCollection<Item> itemInfo;
   public ObservableCollection<Item> ItemInfo 
   { 
     get { return itemInfo; }
     set 
     {
         if(itemInfo!=null)
             itemInfo.CollectionChanged -= ItemInfo_CollectionChanged;

         itemInfo = value;

         if(itemInfo!=null)
             itemInfo.CollectionChanged += ItemInfo_CollectionChanged;

         OnPropertyChanged("ItemInfo");
         OnPropertyChanged("TotalPrice");
}

}

【讨论】:

  • 我将尝试实现这一点。只是为了稍微搅动一下锅,如果我要使用例如:Orderclass 中 Item 类的 2 个显式实例,然后我是否将每个 Item 订阅到相同的 ChangedEvent
  • 这就是 ObservableCollection 的魔力。每当您对此集合的项目进行任何更改时,它都会通知
  • 抱歉,我不是很清楚。我建议不要使用 ObservableCollection,而是使用 Item 的显式实例。
  • 另外,我刚刚注意到您先取消订阅该活动。这是为什么呢?
  • 我这样做是在订阅之前取消订阅事件。就像当您为 ItemInfo 分配新值时,它首先从上一个列表中取消订阅事件。
猜你喜欢
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 2014-07-22
  • 2012-08-05
  • 1970-01-01
  • 2018-01-02
  • 2011-04-04
  • 2017-07-22
相关资源
最近更新 更多