Using Dependency Property and DataBinding in WPF


For some reason, I started looking at Windows Presentation Foundation (WPF) again. I read a book on WPF a while back, it’s a very interesting but has a very steep learning curve (for me anyways). One of the things I did not get about WPF was this new property system called Dependency Properties (DP). I read that the WPF team built this on top of the CLR because they found the existing Property system to be inadequate.

In a nutshell, the DP system is a radical extension to the normal getter/setter Property system we are so familiar with. The interesting thing about DP is that it’s value is not pre-determined, but always resolved, dynamically at run-time, based off a set of rules.

As you might already guessed, DP is used in almost every aspect in WPF, e.g. in Xaml, Attached Properties, triggers..etc. In my opinion, DP system brings for us programmers a new “weapon” in our ever expanding arsenal. One of the cool usage of DP is with Databinding. I really like the ease of being able to databind almost about ANYTHING TO ANYTHING in WPF. I have put together a little demo to showcase using DP and Databinding that looks like this.

dpscreenshot

Demo details:

  1. Created a “MyButton” Class that inherits from System.Windows.Controls.Button.
  2. Registered 4 DP of type integer, defining the Alpha, Red, Green, and Blue values of my button’s background color.
  3. In my Xaml, I put together a couple of sliders, and databinded MyButton‘s DPs to the slider values.

You can view a SWF of the demo here. (you need to have Flash installed in your browser to view this, be patient, takes time to load 🙂 ).

Now let’s look at the code. Here’s the implementation of MyButton class, note the declaration of Dependency Properties.

public class MyButton : Button
{
    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        ChangeBackground();
    }

    #region Properties 

    public int Alpha
    {
        get { return (int)GetValue(AlphaProperty); }
        set { SetValue(AlphaProperty, value); }
    }

    public int Red
    {
        get { return (int)GetValue(RedProperty); }
        set { SetValue(RedProperty, value); }
    }

    public int Green
    {
        get { return (int)GetValue(GreenProperty); }
        set { SetValue(GreenProperty, value); }
    }

    public int Blue
    {
        get { return (int)GetValue(BlueProperty); }
        set { SetValue(BlueProperty, value); }
    }

    #endregion

    public static readonly DependencyProperty AlphaProperty =
        DependencyProperty.Register("Alpha", typeof(int), typeof(MyButton), new FrameworkPropertyMetadata(255, FrameworkPropertyMetadataOptions.AffectsRender)); 

    public static readonly DependencyProperty RedProperty =
        DependencyProperty.Register("Red", typeof(int), typeof(MyButton), new FrameworkPropertyMetadata(255, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty GreenProperty =
        DependencyProperty.Register("Green", typeof(int), typeof(MyButton), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty BlueProperty =
        DependencyProperty.Register("Blue", typeof(int), typeof(MyButton), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));

    private void ChangeBackground()
    {
        this.Background = new SolidColorBrush(Color.FromArgb((byte)Alpha, (byte)Red, (byte)Green, (byte)Blue));
    }
}

Important thing to note here is the DependencyProperty.Register method. FrameworkPropertyMetadataOptions.AffectsRender indicates that any change in the DP will trigger a re-render of the control. Therefore, at the OnRender overridden method, we call a ChangeBackground() method to change the color of the button’s background. Lastly in the getters and setters, we call a GetValue and SetValue, to get/set the DP values. These 2 methods are provided from the base class DependencyObject, which is the common base class of almost all WPF’s Windows Controls.

Let’s look at the Xaml, but only showing the essential stuff. The next snipplet shows the slider controls on my Xaml. These sliders will provide the databinding value for the DPs on my custom button.

<slider Minimum="0" Maximum="180" SmallChange="1" Name="skewXSlider" Margin="4"
        Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" Value="0"/>
<slider Minimum="0" Maximum="180" SmallChange="1" Name="skewYSlider" Margin="4"
        Grid.Row="1" Grid.Column="2" VerticalAlignment="Center" Value="0"/>
<slider Minimum="0" Maximum="360" SmallChange="1" Name="rotateSlider" Margin="4"
        Grid.Row="2" Grid.Column="2" VerticalAlignment="Center" Value="0"/>
<slider Minimum="0" Maximum="255" SmallChange="1" Name="alphaSlider" Margin="4"
        Grid.Row="3" Grid.Column="1" VerticalAlignment="Center" Value="255"/>
<slider Minimum="0" Maximum="255" SmallChange="1" Name="redSlider" Margin="4"
        Grid.Row="4" Grid.Column="1" VerticalAlignment="Center" Value="255"/>
<slider Minimum="0" Maximum="255" SmallChange="1" Name="greenSlider" Margin="4"
        Grid.Row="5" Grid.Column="1" VerticalAlignment="Center" Value="0"/>
<slider Minimum="0" Maximum="255" SmallChange="1" Name="blueSlider" Margin="4"
        Grid.Row="6" Grid.Column="1" VerticalAlignment="Center" Value="0"/>
<slider Minimum="12" Maximum="60" SmallChange="1" Name="fontSizeSlider" Margin="4"
        Grid.Row="7" Grid.Column="2" VerticalAlignment="Center" Value="12"/>
<textbox Name="textbox" Margin="4" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
         FontSize="24" Grid.Column="1" Grid.Row="8" Text="My Button" />

Lastly, this is where the databinding magic happens on the button. When you change the slider values, the button will react accordingly real-time. I really like the ease of hooking this up to other controls on the UI. The Alpha, Red, Green and Blue properties are the custom DPs I implemented on MyButton. The other properties like FontSize, Content, and transformation properties are existing properties on the Button Class. In the WPF Binding syntax, ElementName defines which UI element to wire to, and the Path defines the property we are binding to.

<demo:MyButton Grid.Row="9" Grid.ColumnSpan="2" x:Name="myButton" Margin="5"
      Alpha="{Binding ElementName=alphaSlider, Path=Value}"
      Red="{Binding ElementName=redSlider, Path=Value}"
      Green="{Binding ElementName=greenSlider, Path=Value}"
      Blue="{Binding ElementName=blueSlider, Path=Value}"
      FontSize="{Binding ElementName=fontSizeSlider, Path=Value}"
      Content="{Binding ElementName=textbox, Path=Text}">
 <demo:MyButton.RenderTransform>
   <TransformGroup>
     <RotateTransform Angle="{Binding ElementName=rotateSlider, Path=Value}"
             CenterX="{Binding ElementName=myButton, Path=ActualWidth,
             Converter={StaticResource DivideByConverter}, ConverterParameter=0.5}"
             CenterY="{Binding ElementName=myButton, Path=ActualHeight,
             Converter={StaticResource DivideByConverter}, ConverterParameter=0.5}" />
     <SkewTransform AngleX="{Binding ElementName=skewXSlider, Path=Value}"
             AngleY="{Binding ElementName=skewYSlider, Path=Value}"
             CenterX="{Binding ElementName=myButton, Path=ActualWidth,
             Converter={StaticResource DivideByConverter}, ConverterParameter=0.5}"
             CenterY="{Binding ElementName=myButton, Path=ActualHeight,
             Converter={StaticResource DivideByConverter}, ConverterParameter=0.5}" />
   </TransformGroup>
 </demo:MyButton.RenderTransform>
</demo:MyButton>

If you are interested, the Converter property points to a StaticResource I declared on my Xaml (not shown), which is a converter class that implements IValueConverter. It allows us to write a custom converter for manipulating values. In this case, I wired up my DivideByConverter to CenterX and CenterY, which takes in the ActualWith and ActualHeight of the button, and multiplies that by 0.5 (defined in ConverterParameter). This allows me to Rotate and Skew at the midpoints of the button.

I hope this demo has been of some help. As we have seen, WPF is very flexible and extensible. We could have just as easily databinded our controls to Domain Objects, by setting UI Control’s DataContext, and binding to the object’s properties.

If you like to learn more about Dependency Properties, here are some useful links:

You can download this demo solution here.
You can view the demo here (flash).

Share this post:
Advertisements
Posted in WPF. Tags: . 5 Comments »

5 Responses to “Using Dependency Property and DataBinding in WPF”

  1. Dave M. Says:

    Nice article!

    One thing that I’ve *never* been able to find, and am still trying to locate, is a very simple example that performs two-way binding between a TextBox and a string DependencyProperty in code-behind. Perhaps you can tell me how the XAML should look?

    Here’s my DependencyProperty definition in the code-behind:

    public static readonly DependencyProperty FilePathProperty = DependencyProperty.Register( “FilePath”, typeof(string), typeof(Window1));

    public string FilePath
    {
    get { return (string)GetValue(FilePathProperty); }
    set { SetValue( FilePathProperty, value); }
    }

    And my currently-incorrect XAML:

    File location:

    Thanks!

  2. Dave M. Says:

    whoops… XAML won’t post. Please email me if you’d like me to send it to you.

  3. Dave M. Says:

    Ok, so here’s what I didn’t do correctly — the DataContext. I created the DependencyProperty in my Window, but tried to set the DataContext to something else, and did it incorrectly — all you have to do is put this in your code-behind:

    this.DataContext = this;

    And now the XAML will be able to bind to the DependencyProperty, using something like:

    Hopefully this helps someone out! I spend hours and hours trying to find this bit of info, and fortunately someone on stackoverflow pointed out my mistake.

  4. Roy Says:

    Nice example. Really neat. Helped me understand dependency property. And a nice way to show binding Thanks Ed Foh

  5. Howard Steadman Says:

    I have created Dependency Property in code behind, just like your example. What I need to do is use is in a binding to a multi value converter. I have spent a day truing to figure out the XAML. Please sent what ever goes after “using something like:”


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

%d bloggers like this: