6 Things I Bet You Didn't Know About Data Binding in WPF

Posted Wednesday, January 21, 2009 3:26 PM by Nathan Zaugg

winFX I fell in love with WPF the first time I saw it in action!  WPF is a thing of pure beauty!  Anyway, from the second I saw how the data binding worked I knew that there was going to be a lot to figure out there!  It also seems as though there is no real data binding expert -- or the experts don't blog too much about it.  I created my XAML Cheat Sheet shortly after feeling like I had some kind of grasp on the concept.  It is still a great reference for basic bindings, but when you are real serious about binding you'll have to do better than that.

So I have been working on a project in my spare time called SmartForms 2.0 (more on that later) and I have had to do some very difficult things using bindings.  In my previous experience with WPF I would either create a cleaver type converter and/or just give up and set the value/state of the controls in code (eww!).  This time is different and I have to make data binding work. 

Example #1

Lets say that you need to bind a bool? (nullable boolean) type to a checkbox.

<CheckBox IsChecked="{Binding SomeBooleanField}">Checkbox</CheckBox>

Produces:

DataBound Checkbox

You will notice that the checkbox is in a neither checked nor unchecked state.  Setting IsThreeState="False" doesn't help you as it is false by default. I want the checkebox to be unchecked by default but have no control over the type or the initialization of the type.  Check this out:

<CheckBox IsChecked="{Binding SomeBooleanField, 
TargetNullValue=false}">
Checkbox
</CheckBox>

And now we have normal looking checkboxes!  The best part is that this method doesn't mutate our property.  This was exactly what I was looking for!

DataBound Checkbox Fixed

Example #2

The following XAML is pretty straight forward.  It is simply a text box that we expect to put a city into.

<StackPanel Width="130" Height="40" HorizontalAlignment="Left" 
VerticalAlignment="Top"> <TextBlock>City</TextBlock> <TextBox Text="{Binding SomeTextField}" /> </StackPanel>

Produces:

Databing Textbox No Default

What if the item we are attempting to data bind to is not available.  It's not going to be null, the binding will just fail.  This should work well:

<StackPanel Width="130" Height="40" HorizontalAlignment="Left" 
VerticalAlignment="Top"> <TextBlock>City</TextBlock> <TextBox Text="{Binding SomeTextField,
FallbackValue=UNBOUND}" /> </StackPanel>

Produces:

Databing Textbox Default

Example #3

This is a much more common occurrence.  You have a number that you need to format in a textbox.  This example shows the decimal value with no real format at all.

<StackPanel Width="130" Height="40" HorizontalAlignment="Left" 
VerticalAlignment="Top"> <TextBlock>Cost</TextBlock> <TextBox Text="{Binding SomeDecimalField}" />
</StackPanel>

Produces:

Databing Decimal Non Formatted

There are a few ways to get the format we desire.  The first example uses a static resource:

xmlns:clr="clr-namespace:System;assembly=mscorlib"
<StackPanel Width="130" Height="40" HorizontalAlignment="Left" 
VerticalAlignment="Top"> <StackPanel.Resources> <clr:String x:Key="formatStr">{0:C}</clr:String> </StackPanel.Resources> <TextBlock>Cost</TextBlock> <TextBox Text="{Binding SomeDecimalField,
StringFormat={StaticResource formatStr}}" /> </StackPanel>

You can put the string inline but it looks really funny and for some reason the there has to be a non-whitespace character before the formatting expression which you may not want:

<TextBox Text="{Binding SomeDecimalField, 
StringFormat=Cost: {0:C}}" />

This formats the string to look like "Cost: $1,2398.00".  You can see how that could cause lots of confusion and would be undesirable.  There is a way we can get the binding to work a little better:

<TextBox Text="{Binding SomeDecimalField, 
StringFormat={}{0:C}}" />

OR

<TextBox>
    <TextBox.Text>
        <Binding Path="SomeDecimalField" 
StringFormat="{}{0:C}" /> </TextBox.Text> </TextBox>

The result is a nicely formatted output:

Databing Decimal Formatted

Notice how the binding was applied? This is how you apply MultiBindings which is the next topic.

Example #4

What if you want the value of one or more fields to exist in a single binding?  That is where MultiBindings shine!  Check out this very easy example:

<StackPanel Width="130" Height="40" HorizontalAlignment="Left" 
VerticalAlignment="Top"> <TextBlock>Name</TextBlock> <TextBox> <TextBox.Text> <MultiBinding StringFormat="{}{0}, {1}"> <Binding Path="LastName" /> <Binding Path="FirstName" /> </MultiBinding> </TextBox.Text> </TextBox> </StackPanel>

Results:

Multi Binding

Example #5

Validation can happen at the point of binding. This can be handy if the objects you are binding to have logic built in.  For example, lets say you have a property for birth date.  Obviously the person can not be born in the future!  Here is how we avoid such rotten input!

public DateTime birthdate;
public DateTime BrithDate {
    get { return birthdate; }
    set {
        if (value > DateTime.Today)
            throw new ArgumentException(
"Person can not be born in the future!"); birthdate = value; } }

And the XAML:

<StackPanel Margin="5" Width="130" Height="40" 
HorizontalAlignment="Left"
VerticalAlignment="Top"> <TextBlock>Birthdate</TextBlock> <TextBox Text="{Binding BrithDate, Mode=TwoWay, StringFormat=d, NotifyOnValidationError=true, ValidatesOnExceptions=true}" /> </StackPanel>

Result:

Binding No Error

Binding Error

The error can also be styled if required.  Shown is the default style (nothing custom).

Example #6

The last example is for something called PriorityBinding.  This is poorly named in my opinion as it would be better called CascadingBinding.  The point to PriorityBinding is to name multiple data bindings in order of most desirable to least desirable. This way if the first binding fails, is empty and/or default, another binding can take it's place.  You may have to be a little imaginative to think of such a scenario, but this kind of thing could be useful so I'm glad it's there.  Just for fun, I am using the IsAsync field as well.  This tells WPF to use a thread other than the GUI thread to retrieve this property.  This is important for properties that take a long time to return as it will leave your app unresponsive until the value is bound.  In the case of this example without that attribute the window will not show until the 5 seconds had elapsed.

private string fname;
public string FirstName {
     get {
          Thread.Sleep(5000);
          return fname; 
     }
          set { fname = value; }
}

Xaml:

<StackPanel Margin="5" Width="130" Height="40" 
HorizontalAlignment="Left"
VerticalAlignment="Top"> <TextBlock>Name</TextBlock> <TextBox> <TextBox.Text> <PriorityBinding> <Binding Path="LastNameNonExistant"
IsAsync="True" /> <Binding Path="FirstName"
IsAsync="True" /> </PriorityBinding> </TextBox.Text> </TextBox> </StackPanel>

Result:

Priority Binding

Another neat little thing to know is that the Hierarchy for Binding is Binding -> BindingBase -> MarkupExtension -> Object.  Unlike much of the rest of the .NET Framework you can actually inherit from any of these classes and provide support for your customized binding needs.  That is exactly what I am doing for SmartForms 2.0!  I created a binding class called DataBinding and it looks a little like this:

xmlns:db="clr-namespace:SmartForms2.Binding;assembly=SmartForms2"
<TextBox Name="firstName" Width="175" 
Text="{db:DataBinding Data, DataSource=DB1}" />

My DataBinding class inherits directly from MarkupExtension so all I had to do is implement the abstract method ProvideValue.

Links:

Comments

# Del.icio.us Links for 1/22/2009

Thursday, January 22, 2009 10:33 AM by Frank La Vigne

# Del.icio.us Links for 1/22/2009

Thursday, January 22, 2009 10:34 AM by Frank La Vigne

# Del.icio.us Links for 1/23/2009

Friday, January 23, 2009 9:27 AM by Frank La Vigne

# Newly Noted #9 | Patrick Verbruggen's Blog

Friday, January 23, 2009 11:03 AM by Newly Noted #9 | Patrick Verbruggen's Blog

Pingback from  Newly Noted #9 | Patrick Verbruggen's Blog

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Thursday, January 29, 2009 11:40 PM by Nathan Zaugg

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Friday, January 30, 2009 2:11 AM by Steve Robbins

Nice writeup; Binding is one of those things that's very easy to start working with, but takes quite a while to dig into all the intricacies.

Might be worth just noting that some of these things (like TargetNullValue) are only available in 3.5SP1 or 3.0 SP2.

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Friday, January 30, 2009 10:21 AM by Nathan Zaugg

Thanks for the comment Steve!  I wasn't aware that some of the features were SP specific so thanks again for pointing that out.  

It would sure be nice if 3.5 and 3.5 SP1 were more widely deployed.  I wonder if it's been pushed out via Windows Update yet.

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Friday, January 30, 2009 8:16 PM by RBear

It wont let me download that cheet sheet, says access denied after I registered

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Saturday, January 31, 2009 2:16 AM by Jill Spencer

Nice post) thx

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Saturday, January 31, 2009 10:18 AM by Nathan Zaugg

I changed the permissions and hopefully it will allow you to download it.  If not send me a message to nzaugg (at) gmail (dot) com and I'll email you a copy.

--Nate

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Tuesday, February 03, 2009 2:26 PM by Kevin

Just read this yesterday and needed to use #3 today.  Thanks for the post.

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Tuesday, February 10, 2009 12:30 PM by om

nice

# re: 6 Things I Bet You Didn't Know About Data Binding in WPF

Wednesday, February 11, 2009 5:47 AM by Rich

Awesome.  I've read two full books on WPF cover to cover, and some of this wasn't even mentioned.  Good stuff...

# Designer WPF &raquo; Blog Archive &raquo; Bookmarks for February 20th

Pingback from  Designer WPF  » Blog Archive   » Bookmarks for February 20th

# 6 Things I Bet You Didn't Know About Data Binding in WPF

Monday, March 02, 2009 2:04 PM by kevin Mocha

# TCSWeekly Episode 003 - Silverlight, Moonlight, Kaxaml, Facebook, Multi-touch

Thursday, August 27, 2009 4:07 AM by Microsoft Weblogs

Stories mentioned in this episode: Presidential Inauguration in Silverlight and Moonlight New Version

# Good DataBinding Reference &laquo; This Hours Eternity

Wednesday, October 27, 2010 9:13 AM by Good DataBinding Reference « This Hours Eternity

Pingback from  Good DataBinding Reference « This Hours Eternity

# 6 Things I Bet You Didn&#8217;t Know About Data Binding in WPF - nonocast

Pingback from  6 Things I Bet You Didn’t Know About Data Binding in WPF - nonocast

# 6 Things I Bet You Didn&#8217;t Know About Data Binding in WPF &#8211; Nate&#8217;s Stuff | Around computing

Pingback from  6 Things I Bet You Didn’t Know About Data Binding in WPF – Nate’s Stuff | Around computing

# rimonabantexcellence site title

Wednesday, June 05, 2013 5:54 PM by rimonabantexcellence site title

Pingback from  rimonabantexcellence site title

# 6 Things I Bet You Didn&#8217;t Know About Data Binding in WPF | Saly&#039;s software insights

Pingback from  6 Things I Bet You Didn’t Know About Data Binding in WPF | Saly's software insights