Databinding in WPF/SilverLight

One of the more interesting features of the WPF/SilverLight framework, is databinding. And also one of the more confusing. I’m going to list a few tips here, to serve as a cheat-sheet..

By “source property” I mean that bit of data from which we are taking our value, and the “target property” is what we’re setting. The target property has to be a Dependency Property (DP), but the source can be just about anything.

If you’re going to bind to something that shouldn’t be evaluated until runtime, provide a reasonable default value for your designer to show, and use the following to distinquish which mode you’re in:

Code Snippet
  1. using System.ComponentModel;  // for DesignerProperties
  2. namespace WumPut.DialogWindows
  3. {
  4.     public partial class SampleWindow : Window
  5.     {
  6.         public SampleWindow()
  7.         {
  8.             if (!DesignerProperties.GetIsInDesignMode(this))
  9.             {
  10.                 // not in Design-Mode.
  11.                 this.Title = “Some value thats determined at runtime.”;
  12.             }
  13.             InitializeComponent();
  14.         }

On line 9 of this code snippet, you’re using DesignerProperties.GetIsInDesignMode to determine whether you’re in the VS Designer, or are operating at runtime. To get access to this, include using System.ComponentModel; as shown on line 1.

Here’re some common scenarios..

1. To bind a scalar property of a WPF element to a DP of another WPF element:
(for example)  FontSize=”{Binding ElementName=slider1, Path=Value}“. The curly braces indicate a markup extension.

2. If you want to bind to an attached property of that element, wrap that property in parenthesis. For example, Path=(Grid.Row)

3. To bind to something on a parent element (ie, further up the visual tree):
<TextBlock Text={Binding Path=Title, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}} }

For RelativeSource, ‘FindAncestor’ is just one of several values. It takes a RelativeSourceMode which may be Self, FindAncestor, PreviousData, or TemplatedParent.

4.To set it as a bidirectional binding..
<TextBlock FontSize={binding ElementName=slider1, Path=Value, Mode=TwoWay}

5. For TextBoxes the default behavior is to update the binding upon LostFocus. If you want the trigger to fire as soon as the source content changes, you need to set the UpdateSourceTrigger to PropertyChanged.

6. You can assign a value for the target to take for when the source is null, by using the TargetNullValue property.

For example: <TextBox Text={Binding ThatSourceProperty, TargetNullValue=0″} />

7.. and you can ue the FallbackValue property for defining what the target value will be in the event of an error:

<TextBox Text={Binding ThatSourceProperty, TargetNullValue=0, FallbackValue=1″} />

8. To create that binding in code:
Binding binding = new Binding();
binding.Source = slider1;
binding.Path = new PropertyPath(“Value”);
binding.Mode = BindingMode.TwoWay;
lblSampleText.SetBinding( TextBlock.TextProperty, binding);

You also have available to you in code..
BindingOperations.ClearBinding(..)
BindingOperations.ClearAllBindings()

To get the BindingExpression of a WPF element:
BindingExpressing binding = txtFontSize.GetBindingExpression(TextBox.TextProperty);

9.To bind to objects that aren’t WPF elements:
The information must be in public properties, and instead of ElementName you use one of..
Source
RelativeSource (relative to the current WPF element, i.e.)
DataContext

To bind to a class using a static property (to access an instance of it):
<TextBlock Text=”{Binding
                                    Path=UserName,
                                    Source={x:Static local:Properties.Settings.Default}}” />

Here, Properties is actually the namespace in which class Settings is defined, and Default is a static property that returns an instance of the Settings class. This example is from p59 of Programming WPF.

Note: To bind to your own non-UI class and have your target value update itself as the source property changes, you can implement the INotifyPropertyChanged or the INotifyCollectionChanged interfaces. Before .NET 4 these interfaces were part of the WindowsBase WPF assembly so it was not possible to make your bindings work without referencing that library. As of .NET 4.0 however, the INotify.. interfaces have been type forwarded to System.dll.

10. To bind to something from the .NET class library:
(for example) <TextBlock Text=”{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=Source}”>

11.To bind to an object that you’ve created as a resource:
<Window.Resources>
    <FontFamily x:Key=”CustomFont”>Calibri</FontFamily>
</Window.Resources>

<TextBlock Text=”{Binding Source={StaticResource CustomFont}, Path=Source}”>

12.To bind to a property of the Window itself:
<TextBlock Text=”{Binding Path=Title, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}} }”>

13.To bind to a collection, as in the case of an ItemsControl — which includes the ListBox, ComboBox, and ListView:
<ComboBox ItemsSource=”{Binding Path=Constants.AllowableZoomValues, Mode=OneWay}”
-but don’t forget to set the DataContext in either XAML or your code-behind.

14. The ComboBox.
When I speak of a ‘scalar’ value, I mean a single bit of data, such as an integer or a string. But when we’re talking about a ComboBox or ListBox — these take a collection to be bound to their itemscontrol.

The ComboBox has the ItemsControl property for specifying this. Thus you have a collection of objects to display in it’s drop-down list. But what do you actually show for each element of that list?

ComboBox has the DisplayMemberPath property to specify this. If you set this to a property name that exists on the elements of that collection, the value of that property is what will be displayed.

Let’s take an example: Say we have this simple class..

public class HairyThing
{
public int Id { get; set; }
public string Name { get; set; }
}

and a collection of these defined somewhere within our XAML as a static resource.
We can bind to it as in this XAML..

<ComboBox Name=”cbHairyThings”
ItemsSource=”{Binding Source={StaticResource HairyThings}}” />

This would display the elements by calling their ToString methods. Usually not what you want.

If you change it thus..

<ComboBox Name=”cbHairyThings”
ItemsSource=”{Binding Source={StaticResource HairyThings}}”
DisplayMemberPath=”Name” />

Now it properly displays the Name of the hairy things within the ComboBox and for each item in it’s drop-down list.

If your user selects some item within that ComboBox, you can access that selected value via it’s SelectedItem property..

cbHairyThings.SelectedItem = theHairyThing; // to set the current selection within the ComboBox

var selectedHairyThing = (HairyThing)cbHairyThing.SelectedItem;

ComboBox also provides two other useful properties that relate to our data-binding: SelectedValue and SelectedValuePath.
SelectedValue acts like a more precisely specified SelectedItem. Instead of assigning an entire HairyThing object to it, as you do with SelectedItem, you assign a key property like Id or Name – depending upon the setting of SelectedValuePath.
SelectedValuePath specifies which property to use. If you set SelectedValuePath to Name, then SelectedValue will access the Name property of whatever HairyThing object the SelectedItem is currently bound to.
For example, if you set to Id, as here..

<ComboBox Name=”cbHairyThings”
ItemsSource=”{Binding Source={StaticResource HairyThings}}”
DisplayMemberPath=”Name”
SelectedValuePath=”Id” />

Then when a call to cbHairyThings.SelectedValue gives you back the Id of the currently selected HairyThing..

int id = cbHairyThings.SelectedValue; // Get the Id of the current selection.

cbHairyThings.SelectedValue = 3; // Set the current selection of the ComboBox to the object that has an Id of 3.

I’ll be updating this note as I need to describe the operation of the ComboBox, and to cover more scenarios. Feel free to hit me up with your questions. Best of wishes,  James W. Hurst

Advertisements

About James W Hurst

a professional software designer since the beginning days of the desktop cptr and uC-controlled avionics, I today am focusing on Java, Swift, C# and F# for building mobile and desktop and online applications under Android, Xamarin.Forms, iOS, WPF, and ASP.NET-MVC along with the requisite HTML/CSS/JavaScript/Ajax for web applications. My database expertise has covered a panoply of different database-engines and modeling approaches, and my main area of academic interest is Artificial Intelligence and vision.
This entry was posted in WPF and tagged . Bookmark the permalink.

One Response to Databinding in WPF/SilverLight

  1. Darren says:

    Wonderful beat ! I would like to apprentice even as you amend your site,
    how can i subscribe for a blog web site? The account
    aided me a applicable deal. I have been tiny bit acquainted of
    this your broadcast provided vibrant clear concept

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s