Separated Presentation Patterns

|

It is generally agreed amongst developers that a good clean separation between the visual elements of an application and the logic of an application is a good idea. To that end a number of patterns have emerged over the years:

and more recently:

Over the years I have formed my own ideas as to when, why and where to apply these patterns, and it has been hard going, and to be quite frank, I've been a little inconsistent and vague at times; but recently I have formed more concrete ideas about when, why and where - especially when working with XAML (e.g. WPF and Silverlight) - which I have written down for others to throw stones at, here it is:

In time I plan to add code to illustrate these patterns - as I seem them - to provide more fodder for stone throwing; but in the process hopefully we'll all learn something.

Enjoy! I would love you know what you think and why.

More change notification for Dependency Properties

|

In an earlier post I wrote a little on change notification in relation to dependency properties that you do not own, like those found on a TextBlock or Label. In that post I walked you though using a DependencyPropertyDescriptor, which in essence enables you to add an event handler to a ValueChanged event for any dependency property.

Here's a code example to help illustrate the approach:

DependencyPropertyDescriptor descriptor =
  DependencyPropertyDescriptor.FromProperty
    (UIElement.VisibilityProperty, typeof(UIElement));

descriptor.AddValueChanged
  (this.labelShowHide, new EventHandler(VisibilityChanged));

The example code above creates a instance of a descriptor for the Visibility dependency property owned by the UIElement class, and then adds an event handler called VisibilityChanged. As I pointed out in the previous post there are two issues with this approach:

  • The event handler delegate is of type EventHandler and therefore only passes a simple EventArgs, losing the rich information provided by a typical dependency property change notification via the DependencyPropertyChangedEventArgs, which includes data such as the old and new values of the property.
  • The descriptor approach has a potential memory leak if you're not careful. This is because a reference to your event handler forever roots your class, in a Garbage Collector sense, because the reference is ultimately stored a static Hashtable.

I also think that there is a third, less concrete, issue with this approach: I don't like it. It just feels all wrong; hacking into the hooks provided for the tooling, which does all work fine, but it left me feeling a little dirty ;) There has to be a better way! And there is...

I discovered the proper way to do this kind of change notification a short while ago; however, this is the first opportunity I've had to write up - primarily for me to remember it in the future. The answer is actually quite simple, and related to the approach you would take extending an existing control by using inheritance... a Metadata override!

UIElement.OpacityProperty.OverrideMetadata(
    typeof(TextBlock),
    new FrameworkPropertyMetadata(
        1.0,
        FrameworkPropertyMetadataOptions.Inherits,
        new PropertyChangedCallback(DetailedPropertyChanged)));

The example code above replaces the property metadata for the Opacity dependency property for all TextBlock control instances in scope. The new metadata provides an event handler for change notification, and unlike the descriptor approach the callback is a true dependency property changed event handler:

private void DetailedPropertyChanged(
    DependencyObject d,
    DependencyPropertyChangedEventArgs e)
{
    Debug.WriteLine(string.Format(
        "{0}: old value was '{1}' and the new value is '{2}'",
        e.Property.Name,
        e.OldValue.ToString(),
        e.NewValue.ToString()));
}

Providing access to the old and new values, information about the source and the dependency property that has actually been changed. You now have all the information you could possibly need to handle the changed property; this approach has none of the drawbacks of the previous descriptor approach.

The only thing to be aware of when using this approach is that it impacts the overridden dependency property for all instances of the target type that are in scope; but you have a reference to the target object and property in the event handler, so this is easily coded for via a switch or if statement - it's just something to be aware of.

Here's a simple application that helps to illustrate the approach described here. If you have any comments or questions please leave a comment.

Newer Posts Older Posts Home