Click here to Skip to main content
Click here to Skip to main content

Tagged as

WPF Dependency Property: Compatible with XAML Binding and Code Behind Binding.

, 13 Dec 2010
Rate this:
Please Sign up or sign in to vote.
An easy guideline to write WPF dependency property which is compatible with XAML binding and code behind binding.

Introduction

WPF and dependency property are indispensable parts.

Without dependency property and MVVM, you are almost nowhere in WPF development. But improper use of dependency property can create a nightmare.

Let’s take the following example.

Suppose we have created a custom media player control and we want to bind the Source property from XAML. It is to be noted that once the source property is set, we need to do some additional related thing.

Here is the initial code snippet of Source Dependency Property:

public Uri Source
{
 get { return (Uri)GetValue(SourceProperty); }
 set
 {
       SetValue(SourceProperty, value);
       if (MediaElement != null)
       {
            SetMediaElementSource();
       }
 }
}

// Using a DependencyProperty as the backing store for Source. 
// This enables animation, styling, binding, etc...
   public static readonly DependencyProperty SourceProperty =
        DependencyProperty.Register("Source", typeof (Uri), typeof (MediaPlayer));

And here is our XAML:

<media:MediaPlayer Source="{Binding Source}"   
x:Name="MainPlayer"></media:MediaPlayer>

Now if we run our application, we shall see that none of the code written after SetValue(SourceProperty, value); will execute. The reason behind this is that if we set the property from XAML, the SetValue() method is called directly. So our player will not work if we bind the source property from XAML! We can easily overcome this problem if we use the following overloaded version of DependencyProperty.Register method.

// Using a DependencyProperty as the backing store for Source.  
// This enables animation, styling, binding, etc...
   public static readonly DependencyProperty SourceProperty =
        	DependencyProperty.Register("Source", typeof(Uri), 
	typeof(MediaPlayer), new FrameworkPropertyMetadata(OnMediaSourceChanged));

   private static void OnMediaSourceChanged
	(DependencyObject d, DependencyPropertyChangedEventArgs e)
   {
        var player = d as MediaPlayer;
        if (player != null) player.Source = e.NewValue as Uri;
   }

As you can see, the new FrameworkPropertyMetaData is nothing but a method which is fired once the Source property is changed irrespective of whether it is changed from XAML or code behind. Since we are setting the Source property in OnMediaSourceChanged method so now the Set method of source will execute with all business logic! Seems our problem is solved!! But the fact is it is not solved yet rather it gives birth to another problem. If we set the Source property from the code behind, the Set property of Source along with related code written in Set method will be executed twice, one for setting it from code behind and another from OnMediaSourceChanged method. The solution to this problem is, keep the Set property free from any business logic (or any code!). Rather whatever code is needed to execute, keep those in some separate method and call that method from OnMediaSourceChanged. Here comes the code that is fully compatible with XAML binding and code behind.

/// <summary>
/// Gets or sets the source.
/// </summary>
/// <value>The source.</value>
public Uri Source
{
    get { return (Uri)GetValue(SourceProperty); }
    set
    {
        SetValue(SourceProperty, value);
    }
}

// Using a DependencyProperty as the backing store for Source.  
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty SourceProperty =
    DependencyProperty.Register("Source", typeof(Uri), typeof(MediaPlayer), 
    new FrameworkPropertyMetadata(OnMediaSourceChanged));
    
/// <summary>
/// Called when [media source changed].
/// </summary>
/// The d.
/// The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> 
/// instance containing the event data.
private static void OnMediaSourceChanged
	(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var player = d as MediaPlayer;
    if (player != null)
    {
        player.Source = e.NewValue as Uri;
        player.PostSourceSetupWork();
    }
}

/// <summary>
/// Posts the source setup work.
/// </summary>
public void PostSourceSetupWork()
{
    if (MediaElement != null)
    {
        mediaElement.Pause();
        SetMediaElementSource();
    }
}

History

  • 13th December, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

Share

About the Author

Mahmudul Haque Azad
Software Developer (Senior) Vizrt Bangladesh
Bangladesh Bangladesh
I am truly versatile and 360 degree Engineer having wide range of development experience in .NET and Java Platform. I am also proficient in system level programming in C++. To me technology is not at all a problem, it’s the client requirement that matters! That is I am ready and comfortable to use any technology to make the business of my client a success.
 
In my five years of experience I have the opportunities to work for fortune 500 companies of US and many renowned clients from Europe.
 
My Linkedin Profile: http://bd.linkedin.com/in/mahmudazad
Follow on   Twitter

Comments and Discussions

 
QuestionI like this article. Good job! Pinmemberprendebp4-Mar-12 6:27 
GeneralMy vote of 2 Pinmemberjnebgen14-Dec-10 7:14 
GeneralMy vote of 2 Pinmemberakjoshi13-Dec-10 22:39 
GeneralRe: My vote of 2 PinmemberMahmudul Haque Azad13-Dec-10 23:07 
GeneralMy vote of 4 PinmemberSledgeHammer0113-Dec-10 9:47 
GeneralRe: My vote of 4 [modified] PinmemberMahmudul Haque Azad13-Dec-10 15:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 13 Dec 2010
Article Copyright 2010 by Mahmudul Haque Azad
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid