ailon's DevBlog: Development related stuff in my life

Writing WPF/Silverlight compatible code. Part 5: Adding PropertyChangedCallback

11/30/2009 5:13:27 PM

Note for future readers: These series discuss WPF and Silverlight versions that are current stable versions at the time of this writing – WPF 3.5 and Silverlight 3.

These are ongoing series of posts on the subject of WPF/Silverlight compatibility. New posts will be added to the Table of Contents post as they are written so bookmark that post or just subscribe to my RSS feed.

No OverrideMetadata() Take 2

One thing I didn’t mention in the “No OverrideMetadata()” section of “Part 2: Dependency Properties” is how to add a handler to be called when value of inherited dependency property changes. In WPF you can use OverrideMetadata() method to do it like this:

   1: static MyControl()
   2: {
   3: #if !SILVERLIGHT
   4:     FrameworkPropertyMetadata newMetadata = new FrameworkPropertyMetadata();
   5:     newMetadata.PropertyChangedCallback += MyControl.VisibilityProperty_Changed;
   6:     Control.VisibilityProperty.OverrideMetadata(typeof(MyControl), newMetadata);
   7: #endif
   8: }

Then you do what you wanted to do in your handler which is called every time Visibility changes:

   1: private static void VisibilityProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
   2: {
   3:     // do something here
   4: }

As you know there’s no OverrideMetadata() in Silverlight. So what can we do? Unfortunately, to my knowledge, there’s no elegant way to do this. There are however a couple of not so pretty hacks/workarounds. One is described in an answer to a similar question on StackOverflow.

I’ve used another method which involves an extra DependencyProperty declaration and binding of the original dependency property to this one. In the above mentioned case a Silverlight portion for achieving the same result looks like this:

   1: #if SILVERLIGHT
   2:         // declare an extra DependencyProperty for the workaround
   3:         // It uses the same PropertyChangedCallback as WPF code for Visibility
   4:         private static readonly DependencyProperty VisibilityChangedWorkaroundProperty = DependencyProperty.Register(
   5:             "VisibilityChangedWorkaround", typeof(Visibility), typeof(MyControl),
   6:             new PropertyMetadata(MyControl.VisibilityProperty_Changed));
   7: #endif
   8:  
   9: public MyControl()
  10: {
  11: #if SILVERLIGHT
  12:     // visibility changed event workaround
  13:     Binding visibilityBnd = new Binding("Visibility");
  14:     visibilityBnd.Source = this;
  15:     visibilityBnd.Mode = BindingMode.TwoWay;
  16:     this.SetBinding(MyControl.VisibilityChangedWorkaroundProperty, visibilityBnd);
  17: #endif
  18: }

As you can see above, we’ve declared and extra dependency property called VisibilityChangedWorkaroundProperty and we’ve attached the same handler to it’s property changed event as the one used in the WPF code above. We don’t need a CLR property wrapper for it and we’ve declared it as private so it doesn’t show up anywhere outside of our class. Then in the constructor we bind our new workaround property to the real inherited Visibility property. So, when inherited property changes, our local property changes too, and the callback is called.

kick it on DotNetKicks.com Shout it

Tags: , ,

blog comments powered by Disqus
Copyright © 2003 - 2014 Alan Mendelevich
Powered by BlogEngine.NET 2.5.0.6