2010-10-03 53 views
2

我已經搜索了高和低的解決方案,但我似乎沒有得到它的底部。 像網上的許多帖子,我似乎並沒有讓我的itemPropertyChanged工作。 編輯集合中的項目時不會觸發。爲什麼。ItemPropertyChanged無法在observableCollection上工作。爲什麼?

有點長,但這是我放在一起的一個例子。

我有一個customerViewModel,它包含OrderViewModels集合 編輯數據網格中的順序時,事件不會觸發。

我已經實現了以下功能,但是隻有在加載時才進行編輯。 彷彿它不是事物的同一集合...

INotifyPropertyChanged inpc = OrderViewModels; 
inpc.PropertyChanged += OnItemPropertyChanged; 

有什麼建議?它把我逼瘋

模型

public class Order 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
    public int CustomerId{ get; set; } 
} 

public class Customer 
{ 
    public Customer() 
    { 
     Orders=new ObservableCollection<Order>(); 
    } 

    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Surname{ get; set;} 
    public ObservableCollection<Order> Orders{ get; set;} 

} 

的ViewModels

public class CustomerViewModel : ViewModelBase 
{ 
    private Customer _customerModel; 

    public CustomerViewModel(Customer customerModel) 
    { 
     _customerModel = customerModel; 
     _orderViewModels = new ObservableCollection<OrderViewModel>(); 
     OrderViewModels.CollectionChanged += OnOrdersCollectionChanged; 
     INotifyPropertyChanged inpc = OrderViewModels; 
     inpc.PropertyChanged += OnItemPropertyChanged; 

    } 

    private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     //not firing!!!!!!!!!!!!!!!!!!!!!!!!! 
    } 

    void OnOrdersCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     switch (e.Action) 
     { 
      case NotifyCollectionChangedAction.Add: 
       _customerModel.Orders.Insert(e.NewStartingIndex, ((OrderViewModel)e.NewItems[0]).OrderModel); 
       break; 
      case NotifyCollectionChangedAction.Remove: 
       _customerModel.Orders.RemoveAt(e.OldStartingIndex); 
       break; 
      case NotifyCollectionChangedAction.Replace: 
       _customerModel.Orders[e.OldStartingIndex] = ((OrderViewModel)e.NewItems[0]).OrderModel; 
       break; 
      case NotifyCollectionChangedAction.Move: 
       _customerModel.Orders.Move(e.OldStartingIndex, e.NewStartingIndex); 
       break; 

      default: 
       throw new ArgumentOutOfRangeException(); 
     } 
    } 

    public int Id 
    { 
     get { return _customerModel.Id; } 
     set 
     { 
      _customerModel.Id = value; 
      OnPropertyChanged("Id"); 
     } 
    } 

    public string Name 
    { 
     get { return _customerModel.Name; } 
     set 
     { 
      _customerModel.Name = value; 
      OnPropertyChanged("Name"); 
     } 
    } 

    public string Surname 
    { 
     get { return _customerModel.Surname; } 
     set 
     { 
      _customerModel.Surname = value; 
      OnPropertyChanged("Surname"); 
     } 
    } 
    public Customer CustomerModel 
    { 
     get { return _customerModel; } 
     set 
     { 
      _customerModel = value; 
      OnPropertyChanged(""); 
     } 
    } 

    private ObservableCollection<OrderViewModel> _orderViewModels; 

    public ObservableCollection<OrderViewModel> OrderViewModels 
    { 
     get { return _orderViewModels; } 
     set 
     { 
      _orderViewModels = value; 
      OnPropertyChanged("OrderViewModels"); 
     } 
    } 
} 

public class OrderViewModel:ViewModelBase 
{ 
    private Order _orderModel; 

    public OrderViewModel(Order orderModel) 
    { 
     _orderModel = orderModel; 
    } 

    public int Id 
    { 
     get { return _orderModel.Id; } 
     set 
     { 
      _orderModel.Id = value; 
      OnPropertyChanged("Id"); 
     } 
    } 
    public int CustomerId 
    { 
     get { return _orderModel.CustomerId; } 
     set 
     { 
      _orderModel.CustomerId = value; 
      OnPropertyChanged("CustomerId"); 
     } 
    } 
    public string Description 
    { 
     get { return _orderModel.Description; } 
     set 
     { 
      _orderModel.Description = value; 
      OnPropertyChanged("Description"); 
     } 
    } 

    public Order OrderModel 
    { 
     get { return _orderModel; } 
     set 
     { 
      _orderModel = value; 
      OnPropertyChanged(""); 
     } 
    } 
} 

public class OrderRepository 
{ 
    public static ObservableCollection<Order> GetOrders(int customerId) 
    { 
     return new ObservableCollection<Order> 
       { 
        new Order {Id = 1, CustomerId=1, Description = "MotherBoard"}, 
        new Order {Id = 2, CustomerId=1,Description = "Video Card"}, 
        new Order {Id = 3, CustomerId=1,Description = "TV"}, 
        new Order {Id = 4, CustomerId=1, Description = "Video Recorder"}, 
        new Order {Id = 5, CustomerId=1,Description = "Speakers"}, 
        new Order {Id = 6, CustomerId=1,Description = "Computer"} 
       }; 
    } 
} 

查看

public partial class OrdersView 
{ 
    public OrdersView() 
    { 
     InitializeComponent(); 

     if (!DesignerProperties.GetIsInDesignMode(this)) 
     { 
      var customerVm = 
       new CustomerViewModel(new Customer 
              { 
               Id = 1, 
               Name = "Jo", 
               Surname = "Bloggs" 
              }); 

      var orders = OrderRepository.GetOrders(1); 
      foreach (var orderModel in orders) 
      { 
       customerVm.OrderViewModels.Add(new OrderViewModel(orderModel)); 
      } 
      DataContext = customerVm; 
     } 
    } 
} 

的XAML

<Grid> 
    <DataGrid AutoGenerateColumns="False" AlternationCount="2" ItemsSource="{Binding Path=OrderViewModels}"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Id}" Header="Id"/> 
      <DataGridTextColumn Binding="{Binding CustomerId}" Header="Customer Id"/> 
      <DataGridTextColumn Header="Description" Binding="{Binding Description,UpdateSourceTrigger=PropertyChanged}"/> 
     </DataGrid.Columns> 
    </DataGrid> 
</Grid> 

回答

6
INotifyPropertyChanged inpc = OrderViewModels; 
    inpc.PropertyChanged += OnItemPropertyChanged; 

當上了ObservableCollection<T>變化的任何財產,不是當ObservableCollection<T>項目有自己的特性改變了這種代碼會通知你。例如,當添加或刪除OrderViewModel時,應調用處理程序,因爲Count屬性將在ObservableCollection<OrderViewModel>上更改。

什麼都不傳播OrderViewModel s內的PropertyChanged事件並將它們聚合爲一個單獨的事件。我使用的是類我叫ItemObservableCollection時,我想這樣做:

public sealed class ItemObservableCollection<T> : ObservableCollection<T> 
    where T : INotifyPropertyChanged 
{ 
    public event EventHandler<ItemPropertyChangedEventArgs<T>> ItemPropertyChanged; 

    protected override void InsertItem(int index, T item) 
    { 
     base.InsertItem(index, item); 
     item.PropertyChanged += item_PropertyChanged; 
    } 

    protected override void RemoveItem(int index) 
    { 
     var item= this[index]; 
     base.RemoveItem(index); 
     item.PropertyChanged -= item_PropertyChanged; 
    } 

    protected override void ClearItems() 
    { 
     foreach (var item in this) 
     { 
      item.PropertyChanged -= item_PropertyChanged; 
     } 

     base.ClearItems(); 
    } 

    protected override void SetItem(int index, T item) 
    { 
     var oldItem = this[index]; 
     oldItem.PropertyChanged -= item_PropertyChanged; 
     base.SetItem(index, item); 
     item.PropertyChanged += item_PropertyChanged; 
    } 

    private void item_PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
     OnItemPropertyChanged((T)sender, e.PropertyName); 
    } 

    private void OnItemPropertyChanged(T item, string propertyName) 
    { 
     var handler = this.ItemPropertyChanged; 

     if (handler != null) 
     { 
      handler(this, new ItemPropertyChangedEventArgs<T>(item, propertyName)); 
     } 
    } 
} 

public sealed class ItemPropertyChangedEventArgs<T> : EventArgs 
{ 
    private readonly T _item; 
    private readonly string _propertyName; 

    public ItemPropertyChangedEventArgs(T item, string propertyName) 
    { 
     _item = item; 
     _propertyName = propertyName; 
    } 

    public T Item 
    { 
     get { return _item; } 
    } 

    public string PropertyName 
    { 
     get { return _propertyName; } 
    } 
} 

我可以這樣使用它:

var orders = new ItemObservableCollection<OrderViewModel>(); 
orders.CollectionChanged += OnOrdersChanged; 
orders.ItemPropertyChanged += OnOrderChanged; 
+0

您好,感謝您的reply.just試圖使其工作和compile.Am失蹤「ItemPropertyChanged.Raise」和ItemPropertyChangedEventArgs類。你介意發佈它,以便我可以嘗試。非常感謝。我剛碰到ListCollectionView是否以另一種方式實現相同? – user9969 2010-10-03 11:26:35

+0

不錯。我正在改變我所有的代碼來使用'ItemPropertyChangedEventArgs'設計。以前我只是預先添加了'Item。「當它冒出來的時候,它的屬性名稱會提供更好的解決方案。 – 2010-10-03 12:50:54

+0

你的ItemPropertyChangedEventArgs是什麼樣子的。當你說Raise的意思是Invoke?感謝您的幫助 – user9969 2010-10-04 07:52:30

1

System.ComponentModel.BindingList<Type>提供相同functionnality爲ObservableCollection<Type>和處理正確的PropertyChanged事件。

問候

相關問題