Simple WPF data binding
Written by Mike James   
Monday, 12 July 2010
Article Index
Simple WPF data binding
BindingExpression
Two-way binding

Find out how WPF data binding really works. It's not the binding object that matters - it's the binding expression.

Banner

 

Data binding is often mysterious. You set up a few things and from then on the value of one property, the source, becomes the value of another property, the target.

The mystery is that it all happens automatically without you having to do anything about it - or sometimes it doesn't work and you are left wondering why.

Of course, it's when things go wrong you have to dig inside and find out how things work. In this article we take a look inside before things go wrong and examine the real essence of data binding in WPF. After all this is WPF not w-rocket science.

One of the problems in understanding how data binding works is that most of the explanations attribute the magic to the binding object - this isn't really correct. We need to look more closely at what objects are actually involved in data binding and see exactly what they do.

In this article we look at data binding from code rather than using XAML. The reason is that it is only when you create the objects involved using code that you really understand how things work. XAML adds another layer of abstraction on top of the basics which tends to obscure what is happening.

Once you understand then it is easy to translate to XAML.

The use of DataContext and other properties that have been added to make binding easier are also avoided in an effort to get to the working core of the binding mechanisms. 

Both XAML binding and DataContext will be covered in a future article.

One-way, one-time binding

To understand how anything works it is always a help to start off with the simplest possible case. One way one time binding is about as simple as it gets.

You have a source property and a target property. The one-way binding causes the source property to update the target property with its value just once when the binding is created. That is, this one-way one-time binding is equivalent to an assignment:

target.property=source.property

Don't give up on binding just yet because the next step is to extend it so that the assignment occurs every time the source property changes - and more or less automatically.

The source property can be any get/set property defined as part of a Class but the  target property has to be a dependency property. This tends to limit binding targets to user interface objects but this is usually what we need.

It is usually said that there are three players in the binding business - the source object, the target object and the binding object but in many ways the Binding object is a transitory thing that really doesn't have much to do with the business.

The real third player is the BindingExpression object which is responsible for actually implementing the binding. The reason that it isn't discussed more often is that it lurks in the background and isn't often accessed directly.

In our example the first object we need is the source object which can be an instance of almost any class with a suitable property.  In our example the class is simply:

class SourceClass
{
public int datavalue
  {
    get;
    set;
  }
}

and the property that we are going to use is datavalue.

The target class has to be something with a dependency property and we might as well use an instance of a Textbox - simple drag-and-drop one called Textbox1 onto the window using the XAML designer. In this case we are going to bind to its Text property. Recall that the dependency property that the Text property "backs" is called TextProperty - if you are confused read Inside dependency properties.

First we need an instance of the SourceClass:

SourceClass SourceoOject = new SourceClass(); 

Next we need to create a Binding object. A Binding object is essentially a profile of a binding source. It contains information about the source object and the "path" to the property that is being used as the source of the data - more on paths later.

To define the binding object in this case all we need is:

Binding bind=new Binding();
bind.Source = SourceObject;
bind.Path = new PropertyPath("datavalue");

Notice that the Binding object doesn't have any information about the target object or property and this should give you a clear idea that it can't be the object that is actually responsible for doing the binding. In fact the Binding object is simply a way of potentially being able to set up multiple bindings to the same source object/property.

You also need to be aware of the fact that there is an older Binding object which implemented pre-WPF binding under Windows forms. The WPF Binding object is in System.Windows.Data. The older binding object is in System.Windows.Forms.

To complete the binding we have to use the SetBinding method on the target object:

textBox1.SetBinding(TextBox.TextProperty,bind);

This establishes the connection between the target and source. The target object is specified by the instance that the SetBinding method is called on i.e. textBox1 in this case and its property is specified as the dependency property that is to be updated. Notice that it is the dependency property which is specified.  The source object and its property are specified by the binding object - and this is its main role in life.

Notice that if an object doesn't have a SetBinding method then you can use the static SetBinding method of the BindingOperations class.

Now if you now set the source property

 SourceObject.datavalue = 10;

before the SetBinding operation then when you view the TextBox it will show a value of 10. You can change the source property as much as you like after the SetBinding call and nothing happens - no automatic update. It is in this sense that the binding is one-time.

Now we need to look a little deeper into how the binding actually works and how to update the target property whenever the source property changes.

Banner

<ASIN:0470548657>

<ASIN:047050224X>

<ASIN:0071668950>

<ASIN:0470563486>

<ASIN:1430272058>



Last Updated ( Monday, 12 July 2010 )