Posted by: Zeeshan Amjad | August 14, 2009

DependencyProperty Wrapper in WPF


During the study of dependency property we saw that we usually create a .Net properties wrapper for them. These wrappers are doing nothing but calling the GetValue and SetValue methods of DependencyObject class.

Here is very simple implementation of Dependency Property Wrapper.

  1: public class Employee : DependencyObject
  2: {
  3:     public static readonly DependencyProperty EmpIdProperty =
  4:         DependencyProperty.Register("EmpId", typeof(int), typeof(Employee),
  5:         new PropertyMetadata(0,
  6:             new PropertyChangedCallback(EmpIdCallBack),
  7:             new CoerceValueCallback(CoerceEmpId)));
  8:     public int EmpId
  9:     {
 10:         get { return (int)GetValue(EmpIdProperty); }
 11:         set { SetValue(EmpIdProperty, value); }
 12:     }
 13: }
 14: 

This wrapper is used only in procedural programming languages such as C#, VB.Net, VC++ etc. XAML parser simply ignore these wrapper and directly call the GetValue and SetValue method of dependency object class. What is the disadvantage of this? It simply means if we put any business login inside the .Net property wrapper then XAML parser will simply ignore this. That’s exactly the reason of call back function. We are suppose to put any validation in call back function.

Lets take a look at this by example.

Here we are going to create a simple user control. This user control has one text block as a caption, one text block as a label and one edit box to get input from the user. Here we are going to take input from the user. We restrict that maximum age can not be greater than 99 yeas. Here is the simple XAML code of my user control.

  1: <UserControl x:Class="DependencyPropertyWrapper.MyUserControl"
  2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4:     Height="75" Width="300">
  5:     <StackPanel>
  6:         <TextBlock Background="LightGreen" FontFamily="Vardana" FontSize="16">My User Control</TextBlock>
  7:         <StackPanel Orientation="Horizontal">
  8:             <TextBlock VerticalAlignment="Center" Margin="10">Input Age (Maximum 99)</TextBlock>
  9:             <TextBox VerticalAlignment="Center" Width="100" Name="txtblkTest" Margin="10" Loaded="txtblkTest_Loaded"></TextBox>
 10:         </StackPanel>
 11:     </StackPanel>
 12: </UserControl>
 13: 

And here is a C# code for this user control.

  1: using System;
  2: using System.Windows;
  3: using System.Windows.Controls;
  4: 
  5: namespace DependencyPropertyWrapper
  6: {
  7:     /// <summary>
  8:     /// Interaction logic for MyUserControl.xaml
  9:     /// </summary>
 10:     public partial class MyUserControl : UserControl
 11:     {
 12:         public static DependencyProperty TestProperty =
 13:             DependencyProperty.Register("Test", typeof(int), typeof(MyUserControl));
 14: 
 15:         public int Test
 16:         {
 17:             get 
 18:             { 
 19:                 return (int)GetValue(TestProperty); 
 20:             }
 21: 
 22:             set 
 23:             {
 24:                 if (value > 99)
 25:                     value = 99;
 26:                 SetValue(TestProperty, value); 
 27:             }
 28:         }
 29: 
 30:         public MyUserControl()
 31:         {
 32:             InitializeComponent();
 33:         }
 34: 
 35:         private void txtblkTest_Loaded(object sender, RoutedEventArgs e)
 36:         {
 37:             txtblkTest.Text = Test.ToString();
 38:         }
 39:     }
 40: }
 41: 

Note that in the wrapper .Net properties we are checking if the input value is greater than 99 then set its value is equal to 99.

Here is out simple XAML file to use this user control.

  1: <Window x:Class="DependencyPropertyWrapper.Window1"
  2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4:     xmlns:local="clr-namespace:DependencyPropertyWrapper"
  5:     Title="DependencyProperty Wrapper Demo" Height="300" Width="400" Background="AliceBlue" Loaded="Window_Loaded">
  6:     <Grid>
  7:         <local:MyUserControl x:Name="ustctl" Test="115"></local:MyUserControl>
  8:     </Grid>
  9: </Window>
 10: 

Here is the output of this program.

DependencyPropertyWrapper

Note that the value is set to 115 although we are checking the value in the .net property wrapper.

Now lets try to set the value of this property programmatically. We just add the handler of Window load and write the following code in it.

  1: private void Window_Loaded(object sender, RoutedEventArgs e)
  2: {
  3:         ustctl.Test = 125;
  4: }

Now this will be the output of the program

DependencyPropertyWrapper_02

It means that the dependency property wrapper will be called only in procedural code, and will not call when using directly inside the XAML code.

Advertisements

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

Categories

%d bloggers like this: