WPF: DataBinding

Posted on 2/13/2007 @ 4:18 PM in #Silverlight and WPF by | Feedback | 15652 views

WPF is centered around "UI". So it is reasonable to expect some serious support for DataBinding.

But first, What is DataBinding? Data binding refers to connecting controls with data. So when the data changes, the control changes, and vice versa and all kinds of varieties (more about varieties in a moment).

You can acheive this very easily in WPF. Consider the following XAML -

<Grid Margin="10">
  <Grid.Resources>
    <Style x:Key="txtStyle" TargetType="TextBox">
      <Setter Property="FontSize" Value="15pt"/>
      <Setter Property="HorizontalAlignment" Value="Stretch"/>
      <Setter Property="Margin" Value="10"/>
    </Style>
  </Grid.Resources>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="100"/>
    <ColumnDefinition Width="400"/>
  </Grid.ColumnDefinitions>
   <TextBox Grid.Column="0" Style="{StaticResource txtStyle}"/>
   <ScrollBar Orientation="Horizontal" Grid.Column="1" Minimum="0" Maximum="10" Focussable="true"/>
</Grid>

The above XAML produces a scrollbar and a textbox. The aim now is to change the textbox value as the scrollbar moves, so the scroll bar is the source of my data, and the textbox is the target. Easy. Simply modify the XAML to as follows -

<TextBox 
Grid.Column="0"
Style="{StaticResource txtStyle}"
Name="txtie"
Text="{Binding ElementName=scrollie, Path=Value}" />

Now, when you move the scrollbar, the textbox will reflect it's current value. This can be seen as below -

BUT, if you change the value of the TextBox, the scrollbar doesn't change :-/. How can that be fixed? Easy, change the XAML as follows -

<TextBox 
  Grid.Column="0" 
  Style="{StaticResource txtStyle}" 
  Name="txtie" 
  Text="{Binding ElementName=scrollie, Path=Value, Mode=TwoWay}" />

Wait a minute !! What is "Mode"? It is the "BindingMode" enumeration, and it has the following 4 possible states -

  • OneWay: Source to target.
  • TwoWay: Source to Target and Target to Source
  • OneTime: Source to target - but only once. Good for readonly crap (better performance, because the infrastructure doesn't have to keep a tab on what changed).
  • OneWayToSource: Target to Source.

The default value is "Default" which uses the default Mode value of the binding target. The default value varies for each dependency property. In general, user-editable control properties, such as those of text boxes and check boxes, default to two-way bindings, whereas most other properties default to one-way bindings.

So in this case, we have a TwoWay default behavior, but if you took the textbox out, and replaced it with a Label, OneWay would become default.

But look at OneWayToSource. Target to Source. WTF? Did I just say "Target to Source" databinding? Why the heck would that be useful? Before we can see why "Target to Source" databinding would be useful, let us dive into the C# way of declaring the above databinding. Instead of declaring the Text="{Binding ..}" markup in XML, you could acheive the above using the following C# syntax also:

Binding myBinding = new Binding();
myBinding.Source = scrollie;
myBinding.Path = new PropertyPath(ScrollBar.ValueProperty);
myBinding.Mode = BindingMode.TwoWay;
txtie.SetBinding(TextBox.TextProperty, myBinding);

.. now observe carefully, as I am typing the last line of code, what does Visual Studio tell me in a convenient tool tip -

Uh hoh !! Does this mean, if I needed to DataBind with a property, that isn't supported with a DependencyProperty, I'm screwed? :-/.

Well, yeah pretty much - you cannot truly data-bind with a property that isn't a DependencyProperty (what is a dependency property?), and this is EXACTLY where the OneWayToSource BindingMode enumeration is helpful - it helps you databind with properties that are not supported with a dependency property. w00t!!

Sound off but keep it civil:

Older comments..


On 1/29/2007 7:35:49 AM Jun Meng said ..
BTW, the "DependencyProperty" here is for databinding, which is a sightly different type from the one you mentioned in your "what is a dependency property?" post (Attached Property).


On 1/29/2007 5:48:10 PM Arnaud Weil said ..
Another excellent article! Thanks for clarifying the different BindingMode values.

A few pointless comments:


-The Scrollbar should have a Name="scrollie" attribute


-There's no "Focussable" attribute, it should be written "Focussable"


-Trying your code in XamlPad on Windows XP SP2 with the framework 3.0 installed, it looks like the "TwoWay" value is the default value for the Mode attribute.


On 1/29/2007 7:24:32 PM Sahil Malik said ..
-The Scrollbar should have a Name="scrollie" attribute

<-- Yes. I missed that, I was writing code as I was writing the above blogpost, so I accidentally missed that.

-Trying your code in XamlPad on Windows XP SP2 with the framework 3.0 installed, it looks like the "TwoWay" value is the default value for the Mode attribute.

Per the docs: "Uses the default Mode value of the binding target. The default value varies for each dependency property. In general, user-editable control properties, such as those of text boxes and check boxes, default to two-way bindings, whereas most other properties default to one-way bindings."

LOL :). So we're both wrong - I'll fix the above article.

-There's no "Focussable" attribute, it should be written "Focussable"

<-- I didn't understand that, or maybe I didn't understand that. Maybe I just didn't understand it.


On 1/29/2007 10:07:34 PM Arnaud Weil said ..
Sorry, I copy-pasted too quickly. It should read:


There's no "Focussable" attribute, it should be written "Focusable"

Anyway, thanks for your hard work.

Looks like the default value of the Mode attribute is quite obscure and will result in quite some headaches...


On 4/25/2007 9:42:31 AM Nick said ..
How would you do this with a DataSet? Something like,

Dim ds As New System.Data.DataSet


(etc)


Dim myBinding As New Binding()


myBinding.Source = ds.Tables(0).Rows(0)("Value")


myBinding.Path = New PropertyPath(System.Data.DataRow.SomeUnknownThing)


myBinding.Mode = BindingMode.TwoWay


TextBox1.SetBinding(TextBox.TextProperty, myBinding)

I find it strange Microsoft would omit this, but for the life of me I can't find a Binding.Path for an item inside a DataSet. (I do need two-way binding for my application - the other alternative is spaghetti event codes).


On 8/29/2007 4:55:02 PM Peter Kellner said ..
Nice Article! thanks.

(Your captcha refresh does not seem to work)


On 2/28/2008 12:25:03 AM nik said ..
Hi,


i couldnt get databinding to datagrid or listview as i am trying from


database to show all record in listview.


also couldnt find any datagrid control like vs2005.

Thanks


On 5/12/2011 4:46:23 AM Omar Gamil said ..
i loved this tutorial,i actually loved the way of explaining things more than the material itself :P