Modifying a DataBound Collection - Page 4
       by kirupa  |  9 December 2007

In the previous page, you copied some code and got the application working just the way we wanted. In this page, let's take a look at the code and figure out why things worked the way they did.

Looking at the Code
As you can see, when you submit a name into the textbox, it displays in our listbox. The code for doing all that is only about five lines long, so let's look at each line to figure out what exactly it did:

ObjectDataProvider odp = this.FindResource("PeopleListDS") as ObjectDataProvider;

In the above line, you create a new ObjectDataProvider object, but you initialize it to the ObjectDataProvider already defined for you in XAML. If you recall from the previous page, we found the line in XAML responsible for binding our listbox to our PeopleList ObservableCollection type:

<ObjectDataProvider x:Key="PeopleListDS" d:IsDataSource="True" ObjectType="{x:Type CollectionsDataBinding:PeopleList}"/>

The Key value is very important because it is this value that you use to identify this particular section of your code. In our case, our ObjectDataProvider is keyed to the value PeopleListDS.

To access this value in our code-behind file, you use the FindResource method because our ObjectDataProvider is located in the Resources section of our Window aka this. In other words, you can't use FindResource on whatever you want in the XAML. It has to be stored as a Resource, and you need to know where the resource is stored. In our case, this resource is stored in Window. If you look at the surrounding XAML for the above ObjectDataProvider declaration, you will see that it is indeed nested inside a Window.Resources tag.

Anyway, what gets returned by FindResource is an object of type...object! You will need to cast it appropriately, and that is where the as ObjectDataProvider text comes in. We already know that PeopleListDS is an ObjectDataProvider, and by casting it as such, we make that explicit.

In the end, after this line has executed, your ObjectDataProvider object called odp will store a reference to the existing ObjectDataProvider being used for the data binding between your listbox and PeopleList.


PeopleList people = odp.Data as PeopleList;

The next line is fairly straighforward. Think of your ObjectDataProvider as a wrapper for the data used in the data binding relationship between a target and a source. In this line, you are essentially digging through the wrapper and getting at the data directly using your ObjectDataProvider odp object's Data property.

Because our ObjectDataProvider is wrapping our PeopleList class, when you access odp's Data, you are actually accessing the PeopleList instance used. Just like before, I am casting the value retuned into the type we want, which in this case is PeopleList.


Person newPerson = new Person();
newPerson.PersonName = NameInput.Text;

Finally, something easy! In these two lines, I am creating a new Person object and setting it's PersonName property to the text you entered in your textbox. The reason I am creating a new Person object is because our PeopleList stores data in the form of Person objects only.


people.Add(newPerson);

In this line, I add the new person you created earlier to the PeopleList instance we extracted from our ObjectDataProvider. After this line executes, your newPerson gets added to the Listbox with the person's name displayed.

Let's spend some looking at that last line in greater detail. Why is it that simply adding the name to our PeopleList instance updates the listbox accordingly? The reason is that data binding requires a target and a source. The target is usually a visual element, and in our case, that was a listbox. The source is the place your data comes from. The source in this project is the PeopleList collection.

In order for our target to update, it needs to first know that a change has been made to the source. Internally, that is handled by Notify events. Any class that implements either the INotifyChanged or INotifyCollectionChanged interfaces is capable of sending out change notifications that can be heard, understood, and acknowledged by a target.

You may be asking if our code contains any implementations of either INotifyChanged or INotifyCollectionChanged. The answer is yes - indirectly via our ObservableCollection. The ObservableCollection class is, for the most part, just a regular Collection with INotifyCollectionChanged implemented. This means that, whenever an item is added or removed from our ObservableCollection object, a change notification is fired. Because PeopleList extends ObservableCollection, it too inherits there superhero powers from the ObservableCollection class.


Ok, so you have your application working and you saw how the code works. Beyond that, you probably learned more than you really wanted about how your listbox knew when to update when a new Person was added.

Surprisingly, there is actually one more topic I want to discuss. Part of data binding is to provide a clean separation between visuals and logic. In the next page, I will explain how to improve what we have currently written to more clearly separate the logic from the UI.

Onwards to the next page!

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.