Implementing CollectionChanged Implementing CollectionChanged wpf wpf

Implementing CollectionChanged


You have to add a PropertyChanged listener to each item (which must implement INotifyPropertyChanged) to get notification about editing objects in a observable list.

public ObservableCollection<Item> Names { get; set; }public List<Item> ModifiedItems { get; set; }public ViewModel(){   this.ModifiedItems = new List<Item>();   this.Names = new ObservableCollection<Item>();   this.Names.CollectionChanged += this.OnCollectionChanged;}void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e){    if (e.NewItems != null)    {        foreach(Item newItem in e.NewItems)        {            ModifiedItems.Add(newItem);            //Add listener for each item on PropertyChanged event            newItem.PropertyChanged += this.OnItemPropertyChanged;                 }    }    if (e.OldItems != null)    {        foreach(Item oldItem in e.OldItems)        {            ModifiedItems.Add(oldItem);            oldItem.PropertyChanged -= this.OnItemPropertyChanged;        }    }}void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e){    Item item = sender as Item;    if(item != null)       ModifiedItems.Add(item);}

Maybe you have to check if some item is already in the ModifedItems-List (with List's method Contains(object obj)) and only add a new item if the result of that method is false.

The class Item must implement INotifyPropertyChanged. See this example to know how. As Robert Rossney said you can also make that with IEditableObject - if you have that requirement.


An ItemsControl listens to CollectionChanged to manage the display of the collection of items it's presenting on the screen. A ContentControl listens to PropertyChanged to manage the display of the specific item that it's presenting on the screen. It's pretty easy to keep the two concepts separate in your mind once you understand this.

Tracking whether or not an item is edited isn't something either of these interfaces does. Property changes aren't edits - that is, they don't necessarily represent some kind of user-initiated change to the state of the object. For instance, an object might have an ElapsedTime property that's being continuously updated by a timer; the UI needs to be notified of these property-change events, but they certainly don't represent changes in the object's underlying data.

The standard way to track whether or not an object is edited is to first make that object implement IEditableObject. You can then, internally to the object's class, decide what changes constitute an edit (i.e. require you to call BeginEdit) and what changes don't. You can then implement a boolean IsDirty property that gets set when BeginEdit is called and cleared when EndEdit or CancelEdit is called. (I really don't understand why that property isn't part of IEditableObject; I haven't yet implemented an editable object that didn't require it.)

Of course, there's no need to implement that second level of abstraction if you don't need it - you can certainly listen PropertyChanged event and just assume that the object has been edited if it gets raised. It really depends on your requirements.


My edit to 'this answer' is rejected!So I put my edit here:

void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e){if (e.NewItems != null){    foreach(Item newItem in e.NewItems)    {        ModifiedItems.Add(newItem);        //Add listener for each item on PropertyChanged event        if (e.Action == NotifyCollectionChangedAction.Add)            newItem.PropertyChanged += this.ListTagInfo_PropertyChanged;        else if (e.Action == NotifyCollectionChangedAction.Remove)            newItem.PropertyChanged -= this.ListTagInfo_PropertyChanged;    }}// MSDN: OldItems:Gets the list of items affected by a Replace, Remove, or Move action.  //if (e.OldItems != null) <--- removed}