Geeks With Blogs
Subodh Pushpak Technical musings on Win8, mobile (iOS / android / WP7) and WCF

Dependency properties is one concept which i always marvel. As programmer / developer i always like the concept, as by just introducing DP, so many stuff now is so easy(Read Template programming in XAML).

DP is called a BEAST (in Silverlight and WPF) for reasons of complexity involved in understanding them. Also, of course, because they are so powerful language paradigm. I sometimes do think DP did not actually got their due. I mean, so many efforts is gone into explaining Lambda expressions, LINQ, and other stuff but DP still remains a taboo.

So, when i took up to the task of explaining WPF, many were skeptical about my thought of actually introducing DP in second session itself. (the audiences had people from testing and not-so-much-into-coding). But i have always felt, new programming concept are like mathematics, once you have the concept, its interesting. But, mostly the concept part is ignored and then it all becomes a mystery.

here is a whirlwind introduction of DP… The ppts are here and the demo code here.

Below is explanations:

Purpose of dependency properties is to compute the value of a property based on values of other inputs available

 

DPs provide for

–Change Notification

–Callbacks

–Property value validation

–Property value inheritance *

–Participation in animations *

–Participation in Styles *

–Participation in Templates *

–Data binding

–Layout changes *

Overriding default data values *

Example 1 – Explaining DP visual inheritance

consider:

   1: <Window x:Class="Demo2.Window1"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" TextElement.FontSize="15"
   4:     Title="Window1" Height="300" Width="300">
   5:     <StackPanel>
   6:         <TextBlock Text="this has inherited Fonstsize DP property"></TextBlock>
   7:         <TextBlock Text="this has its own Fonstsize DP property" FontSize="20"></TextBlock>
   8:     </StackPanel>
   9: </Window>

output is : The one encircled in Red inherits Font size from visual parent Window, which sets TextElement.FontSize to 15. The one encircled in Blue overrides this to font size 20.

DP1

Example2: Now lets implement our own version of DP inheritance for POC. The idea is to introduce a new DP “Text” for stackpanel which is propagated to its visual children DP.

Consider:

   1: namespace Demo2
   2: {
   3:     /// <summary>
   4:     /// Interaction logic for Window2.xaml
   5:     /// </summary>
   6:     public partial class Window2 : Window
   7:     {
   8:         public Window2()
   9:         {
  10:             InitializeComponent();
  11:         }
  12:     }
  13:     public class MyStackPanel : StackPanel
  14:     {
  15:  
  16:  
  17:         public string Text
  18:         {
  19:             get { return (string)GetValue(TextProperty); }
  20:             set { SetValue(TextProperty, value); }
  21:         }
  22:  
  23:         // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
  24:         public static readonly DependencyProperty TextProperty =
  25:             DependencyProperty.Register("Text", typeof(string), typeof(MyStackPanel), 
  26:             new FrameworkPropertyMetadata("stackPanel Default Text",
  27:                 FrameworkPropertyMetadataOptions.Inherits));
  28:  
  29:     }
  30:  
  31:  
  32:     public class MyButton : Button 
  33:     {
  34:         public string Text
  35:         {
  36:             get { return (string)GetValue(TextProperty); }
  37:             set { SetValue(TextProperty, value); }
  38:         }
  39:  
  40:         // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
  41:         public static readonly DependencyProperty TextProperty =
  42:             MyStackPanel.TextProperty.AddOwner(typeof(MyButton), 
  43:             new FrameworkPropertyMetadata("Button Default Text", FrameworkPropertyMetadataOptions.Inherits));
  44:     }
  45: }

We have added DP for both StackPanel and button. However in Button the DP is registered as

public static readonly DependencyProperty TextProperty =
            MyStackPanel.TextProperty.AddOwner(typeof(MyButton),
            new FrameworkPropertyMetadata("Button Default Text", FrameworkPropertyMetadataOptions.Inherits));

now here are scenarios:

1. if we set Text DP for both MyStackPanel and MyButton as below

   1: <StackPanel>
   2:         <local:MyStackPanel x:Name="sp" Text="This is Test set by StackPanel">
   3:             <ContentPresenter Content="{Binding ElementName=sp, Path=Text}" ></ContentPresenter>
   4:             <local:MyButton Text="This is text set by MyButton"
   5:                 Content="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text}"                           
   6:                             ></local:MyButton>
   7:         </local:MyStackPanel>
   8:     </StackPanel>

output is

image 

2. if we set ONLY the Text in MYstackpanel, the MYButton Text will inherit from visual parent as below

   1: <local:MyStackPanel x:Name="sp" Text="This is Test set by StackPanel">
   2:             <ContentPresenter Content="{Binding ElementName=sp, Path=Text}" ></ContentPresenter>
   3:             <local:MyButton 
   4:                 Content="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text}"                           
   5:                             ></local:MyButton>
   6:         </local:MyStackPanel>

image Notice button caption is same as Stackpanel

3. If we Do NOT set any text, the TEXT will assume default values for BOTH.

image 

4. If we only set Button Text DP

   1: <local:MyStackPanel x:Name="sp" >
   2:            <ContentPresenter Content="{Binding ElementName=sp, Path=Text}" ></ContentPresenter>
   3:            <local:MyButton Text="This is text set by MyButton"
   4:                Content="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text}"                           
   5:                            ></local:MyButton>
   6:        </local:MyStackPanel>
image

Notice in above case the Text DP is still default for stackpanel. that is DP is NOT propogated to visual parent from child.

We want to achieve the above case we have to make Attached DP property. I which parent property may be changed by the child element contained in parent

Attached DP Property

for this we will override an stackpanel and expose a Attached DP text which may be set by ANY visual children.

   1: <StackPanel>
   2:        <local:MyStackAttached x:Name="sp">
   3:            <Button x:Name="btn" local:MyStackAttached.Text="This text set by child button" Content="OK"></Button>
   4:        </local:MyStackAttached>
   5:        <TextBox x:Name="textBox" ></TextBox>
   6:    </StackPanel>

   1: namespace Demo2
   2: {
   3:     /// <summary>
   4:     /// Interaction logic for Window3.xaml
   5:     /// </summary>
   6:     public partial class Window3 : Window
   7:     {
   8:         public Window3()
   9:         {
  10:             InitializeComponent();
  11:             // notice , we are getting DP value from btn and NOT stackpanel :D
  12:             textBox.Text =  (string)btn.GetValue(MyStackAttached.TextProperty);
  13:         }
  14:     }
  15:  
  16:     public class MyStackAttached : StackPanel
  17:     {
  18:         static ContentPresenter contentPresenter = new ContentPresenter() { Height = 100.0, Width = 200.0 };
  19:  
  20:         public MyStackAttached()
  21:         {
  22:             base.Children.Add(contentPresenter);
  23:         }
  24:  
  25:         public static string GetText(DependencyObject obj)
  26:         {
  27:             return (string)obj.GetValue(TextProperty);
  28:         }
  29:  
  30:         public static void SetText(DependencyObject obj, string value)
  31:         {
  32:             obj.SetValue(TextProperty, value);
  33:         }
  34:  
  35:         // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
  36:         public static readonly DependencyProperty TextProperty =
  37:             DependencyProperty.RegisterAttached("Text", typeof(string), typeof(MyStackAttached),
  38:             new UIPropertyMetadata((o, e) =>
  39:             {
  40:                 contentPresenter.Content = GetText(o); 
  41:             }
  42:             ));
  43:     }
  44: }

output:

image

Data Validation, Coerce using DP

The idea is to create a textbox which accepts only correct AGE values between 1 and 100. This is achieved by exposing a DP AGE.

   1: public class MyTextBox : TextBox
   2:    {
   3:        public int Age
   4:        {
   5:            get { return (int)GetValue(AgeProperty); }
   6:            set { SetValue(AgeProperty, value); }
   7:        }
   8:  
   9:        // Using a DependencyProperty as the backing store for Age.  This enables animation, styling, binding, etc...
  10:        public static readonly DependencyProperty AgeProperty =
  11:            DependencyProperty.Register("Age", typeof(int), typeof(MyTextBox), new FrameworkPropertyMetadata(1,
  12:            FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback((o, e) => { }), new CoerceValueCallback((o, e) =>
  13:            {
  14:                int current = (int)e;
  15:                if (current <=0 )
  16:                    current = 1;
  17:                return current;
  18:            })),
  19:             new ValidateValueCallback((o) =>
  20:             {
  21:                 int current = (int)o;
  22:                 if (current > 100)
  23:                 { return false; }
  24:                 else
  25:                 { return true; }
  26:             }));
  27:    }
the XAML looks like:

   1: <StackPanel>
   2:         <TextBox x:Name="mytext"></TextBox>
   3:         <local:MyTextBox Age="{Binding ElementName=mytext, Path=Text, Mode=TwoWay}"
   4:                         Text="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Age, Mode=TwoWay}" 
   5:                          ></local:MyTextBox>
   6:     </StackPanel>

Output:

imageWhen Age value is <= 0 , the Age=1

image When age is valid

image  when age > 100 then Age =1

 

Along with above i have also included a unit test case for the last scenario in the code.

Your thoughts / comments are welcome:

Technorati Tags: ,,,
Posted on Friday, September 18, 2009 11:35 AM | Back to top


Comments on this post: Dependency Properties

# re: Dependency Properties
Requesting Gravatar...
I'm wondering how can I inherit property values in behavior.

E.g. if you added behavior to your MyTextBox, and your behavior also had "Age" property, how could the behavior Age property inherit from MyTextBox age...
Left by Ciantic on Oct 14, 2009 7:59 PM

# re: Dependency Properties
Requesting Gravatar...
Great post, thanks !
Left by James on Nov 28, 2009 2:46 PM

# re: Dependency Properties
Requesting Gravatar...
Great info! Thanks!

Chad
Left by Chad on Mar 06, 2010 9:27 PM

# re: Dependency Properties
Requesting Gravatar...
Thank you for the DP tutorial. I was searching for the Text Box creation code based on condition. Have a great time.
Left by Jasson on Mar 20, 2010 6:48 PM

# re: Dependency Properties
Requesting Gravatar...
nice post. thanks for the tutorial!

mr prolong
Left by Mr Prolong on Aug 10, 2010 5:15 PM

# re: Dependency Properties
Requesting Gravatar...
i found this very useful.Prgogramming is not my cup of tea! I didnot know about creating text box.
Left by Linda on Sep 20, 2010 3:42 PM

# re: Dependency Properties
Requesting Gravatar...
Wonderful post. I really love it.

http://yeastinfectionhomeremedycures.org
Left by Melinda on Feb 16, 2011 4:50 PM

# re: Dependency Properties
Requesting Gravatar...
Great post. Thanks for the DP tutorial. Best of luck.
Left by Instant Cash Empire Bonus on Feb 27, 2011 5:28 PM

# re: Dependency Properties
Requesting Gravatar...
I have truly enjoyed reading your blog posts. You obviously know your stuff. I also really like it that your website is very simple to navigate. I have bookmarked it in my favorites and will for sure be back for more. Thanks.
Left by Kurierportal on Mar 01, 2011 3:35 PM

# re: Dependency Properties
Requesting Gravatar...
So glad I stumbled on your site when looking for more information on article marketing. Thanks for sharing this post.

http://fussmatten-shop.eu
Left by Susan@Fußmatten on Mar 03, 2011 1:25 PM

# re: Dependency Properties
Requesting Gravatar...
Nice article……I was searching these kind of information ,Thank you so much…..
Forex Managed Accounts
Left by managed forex accounts on Apr 09, 2011 12:28 AM

# re: Dependency Properties
Requesting Gravatar...
interest article and helpful information, Thanks

OBDII scanner
Left by OBD scanner on May 23, 2011 3:11 PM

Your comment:
 (will show your gravatar)


Copyright © subodhnpushpak | Powered by: GeeksWithBlogs.net