2010-10-03 43 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事件。

问候

相关问题