tags:

views:

69

answers:

5

I was learning about ObservableCollections in WPF and something is not clear to me. I understand that if I bind a control to an ObservableCollection and the collection changes, the control will reflect the changes. My questions are:

  • ObservableCollection implements INotifyCollectionChanged, which is just an event, CollectionChanged. That event should be fired whenever the collection changes but who subscribes to that event? Is it done automatically when you create a binding to the collection?

  • I was looking at ObservableCollection using Reflector and was trying to see when the CollectionChanged event gets fired. However I couldn't find where it is done. For example, I wanted to see when it was fired when I added a new item to the collection. Add(...) is implemented in ObservableCollection's base class, Collection, but Collection does not implement INotifyCollectionChanged so I don't understand how bound controls are notified of the change.

I am guessing that a lot of this is taken care of under the covers but any info is greatly appreciated.

A: 

Simple plain english answer:

ObservableCollections update controls they are databound to when objects are added or removed from the collections.

They do NOT update databinding when objects in the collection are modified.

Scrappydog
Yes, I understand that part. I am not concerned with the items in the collection though. My questions refer to the collection itself (who is listening to the collection's "changed" events and when is the event fired when a new item is added to the collection).
Flack
A: 

From reflecting .Net 3.5, Collection<T>'s Add() method calls InsertItem:

public void Add(T item)
{
    //...
    int count = this.items.Count;
    this.InsertItem(count, item);
}

InsertItem() is overridden in ObservableColletion<T>, which does the notifying:

protected override void InsertItem(int index, T item)
{
    this.CheckReentrancy();
    base.InsertItem(index, item);
    this.OnPropertyChanged("Count");
    this.OnPropertyChanged("Item[]");
    this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
}
Grant Crofton
Darn, I don't know how I missed the override. Thanks for clearing it up for me.
Flack
A: 

@Grant Crofton's answer provides where the "meat and potatoes" of INotifyCollectionChanged is inside of ObservableCollection<T>. However, to answer your first question you should read up on WPF and Binding Sources.

Basically, when you bind an object in WPF, it is checked against certain "contracts", one of which is INotifyCollectionChanged. WPF handles attaching to the event and receiving the notifications. The Control then determines how to respond when it is notified of an update to one of its DependencyProperty objects.

Interestingly enough, WPF uses a View of a Collection rather than the collection itself in a binding:

WPF never binds directly to a collection. If you specify a collection as a binding source, WPF actually binds to the collection's default view. For information about default views, see Data Binding Overview.

sixlettervariables
+1  A: 

That event should be fired whenever the collection changes but who subscribes to that event? Is it done automatically when you create a binding to the collection?

The Binding object subscribes to the source's CollectionChanged and/or PropertyChanged events.

Robert Rossney
I don't think this is entirely true? See my example below.
karmicpuppet
I'll be damned. So I would guess that when the `Binding` sets the `ItemsSource`, it's the `ItemsSource` setter that creates the `ItemContainerGenerator` and hooks it up the collection-changing events. This means that the `Binding` doesn't care whether or not the property it's binding is a collection. That makes a great deal of sense.
Robert Rossney
+2  A: 
karmicpuppet
Thanks for the detailed explanation. It makes much more sense now.
Flack