Brian Genisio's House of Bilz

  Home  |   Contact  |   Syndication    |   Login
  62 Posts | 0 Stories | 118 Comments | 0 Trackbacks

News

Locations of visitors to this page

Archives

Post Categories

Who am I?

Monday, January 11, 2010 #

More Adventures in MVVM

So, I am getting myself ready to head out to Sandusy, Ohio for three days of nerdy fun at CodeMash.  While I am there, I will be giving my “Introduction to the MVVM Pattern”.  In preparation for this talk, I decided to create a new demo application.  This application is a calendar and session list for the conference.  It is not terribly fancy (I wish I had more time (or talent) to skin it better), but it highlights many of the concepts that I will be speaking about in my presentation.

The app is a Silverlight 3 project utilizing the Telerik Scheduler control.  This particular control is rather rich, and I was excited to get my hands dirty with it. The ViewModel for the scheduler was primarily responsible for translating session data into something the Telerik control could consume.   The app also includes a session list with a filter panel which is derived from the session data.  This is where the majority of the MVVM code can be found.  The ViewModels for the session list are responsible for dynamically creating and merging filter predicates based on the values in the session list. 

CodeMashSessions.Calendar CodeMashSessions.Sessions

You can play with the application at http://HouseOfBilz.net/CodeMash

CodeMashSessions Source Code: http://www.houseofbilz.net/codemash/CodeMashSessions.Source.zip

Twitter "Ball of Mud" vs MVVM Source Code: http://houseofbilz.net/codemash/Twitter-BallOfMud-vs-MVVM.zip

Slides from "An Introduction to the MVVM Pattern": http://houseofbilz.net/codemash/MVVM.ppt

 


Sunday, December 20, 2009 #

Four years ago, I moved to Ann Arbor to work with a talented team on what I consider to be an important, high-quality medical application.  In that time, I had many great opportunities and I learned a ton from my colleagues.  My team is filled with some really smart people!  Because of this, I have mixed feelings to announce that I am moving on.  Starting in February, I will be working for Bill Wagner and Dianne Marsh and joining the team at SRT Solutions.  It will be quite a change for me -- moving from one of the largest companies in the world to a small, local consulting company.  This job will, however, give me an opportunity to spend more time focusing on the technologies and concepts that most interest me.  I am excited for this change, and I am excited to be working directly with the many amazing members of the SRT team.


Saturday, November 14, 2009 #

More Adventures in MVVM Shout it kick it on DotNetKicks.com

I spend a lot of time writing ViewModels, which almost always implements INotifyPropertyChanged.  For those who are not familiar with this interface, it includes a single event: PropertyChanged.  That event contains a payload of the name of the property that changed.  It exists as a standard way to notify observers that a property needs to be re-evaluated.

Although I use it all the time, I have always believed that INotifyPropertyChanged has some serious shortcomings.  One of those shortcomings deals with dependant properties. 

Lets say, for for the sake of example, that the ViewModel has two integer properties that the user can enter (InputA and InputB).  There also exists a property named Calculation that is dependent upon InputA and InputB.  Finally, there is a display property named CalculationText which is dependent upon Calculation.  The code for these properties would look like this:

private int _inputA;
public int InputA
{
    get { return _inputA; }
    set
    {
        if (_inputA == value) return;

        _inputA = value;
        RaisePropertyChanged("InputA");
        RaisePropertyChanged("Calculation");
        RaisePropertyChanged("CalculationText");
    }
}

private int _inputB;
public int InputB
{
    get { return _inputB; }
    set
    {
        if (_inputB == value) return;

        _inputB = value;
        RaisePropertyChanged("InputB");
        RaisePropertyChanged("Calculation");
        RaisePropertyChanged("CalculationText");
    }
}

public int Calculation
{
    get { return InputA * InputB; }
}

public string CalculationText
{
    get { return "A * B = " + Calculation; }
}

There is a problem with this code.  The input properties need to know that they are inputs for Calculation and CalculationText by firing the event for the calculations.  As far as I am concerned, this is the wrong place for this information to exist.  Inputs should not know that they are inputs.  I can say first hand that this quickly breaks down as the ViewModel gets bigger and you start changing behavior.

The responsibility should be reversed.  Instead of having the input properties knowing about the dependants, the dependent properties should be responsible for knowing the inputs that they rely upon.  This can be done with some simple declarations:

private int _inputA;
public int InputA
{
    get { return _inputA; }
    set
    {
        if (_inputA == value) return;

        _inputA = value;
        RaisePropertyChanged("InputA");
    }
}

private int _inputB;
public int InputB
{
    get { return _inputB; }
    set
    {
        if (_inputB == value) return;

        _inputB = value;
        RaisePropertyChanged("InputB");
    }
}

[DependsUpon("InputA")]
[DependsUpon("InputB")]
public int Calculation
{
    get { return InputA * InputB; }
}

[DependsUpon("Calculation")]
public string CalculationText
{
    get { return "A * B = " + Calculation; }
}

Notice how Calculation declares that it is dependent upon InputA and InputBCalculationText also declares a dependency upon Calculation.  The inputs are free of knowing anything about the dependants.

The implementation of this behavior should be handled in the base class and there are several ways to accomplish it.  There are just a few things you want to think about:

  1. Make sure that when inputs fire a change notification, the dependants are also fired
  2. Make sure to handle dependency chaining.  InputA will cause Calculation to fire and Calculation will cause CalculationText to fire
  3. If the derived class declares dependencies such that it creates a circular reference, don’t endlessly loop or overflow your stack

Here is a very simple implementation of this behavior.  It manages the reflection at the time of change.  A better (more efficient) implementation would probably map the dependencies at construction time into a private dictionary, but this is just a quick example of how you might achieve this behavior:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
    protected class DependsUponAttribute : Attribute
    {
        public string DependancyName { get; private set; }
        
        public DependsUponAttribute(string propertyName)
        {
            DependancyName = propertyName;
        }
    }

    protected virtual void RaisePropertyChanged(string propertyName)
    {
        var handlers = PropertyChanged;
        if (handlers != null)
        {
            foreach(var property in AllNotifiedProperties(propertyName))
                handlers(this, new PropertyChangedEventArgs(property));
        }
    }

    private IEnumerable<string> DependantProperties(string inputName)
    {
        return from property in GetType().GetProperties()
               where property.GetCustomAttributes(typeof(DependsUponAttribute), true).Cast<DependsUponAttribute>()
                     .Any(attribute => attribute.DependancyName == inputName)
               select property.Name;
    }

    private IEnumerable<string> NotifiedProperties(IEnumerable<string> inputs)
    {
        var dependancies = from input in inputs
                           from dependancy in DependantProperties(input)
                           select dependancy;

        return inputs.Union(dependancies).Distinct();
    }

    private IEnumerable<string> AllNotifiedProperties(string inputName)
    {
        IEnumerable<string> results = new[]{inputName};

        while (NotifiedProperties(results).Count() > results.Count())
            results = NotifiedProperties(results);

        return results;
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Tuesday, October 20, 2009 #

More Adventures in MVVM Shout it kick it on DotNetKicks.com

I have been taking a few weeks off from my personal studies/experiments in the .Net space to learn more about Ruby and Ruby on Rails (RoR).  I have two main goals for this study:

  1. Get to know another platform as an option for future development
  2. Examine how I can incorporate different concepts into my existing framework

What follows is intended to document my experimentation with the second bullet:  How might we design a ViewModel if we were in Rails?  My thoughts on this are still forming, and I am still a novice in the RoR arena, so cut me some slack :).

I am pretty vocal about my thoughts on the MVVM pattern.  I really like the pattern a lot and I think it solves a lot of problems that I encounter on a daily basis.  Unfortunately, the implementation of the pattern – ViewModels specifically – often get overly complicated.  This is why there are about a dozen major players in this arena.  The plumbing necessary to create a good ViewModel is tedious and error prone.  A good set of abstractions and tools make the job much easier.

The RoR approach to application development uses a lot of conventions to allow the developer to be as expressive as possible without introducing too much plumbing.  The framework facilitates DRY (Don’t Repeat Yourself) so your controllers declare what they do and the magic under the hood plumbs it all together for you.  How can we translate these ideas to a better implementation of the MVVM pattern?  In this article, I will focus on the ViewModel portion of the MVVM pattern.

A classic ViewModel implementation

This view is simple.  There is a text box bound to the Text property in the ViewModel and a button bound to the MakeLowercase command (property) in the ViewModel.  The button is enabled/disabled based on the length of the Text property and clicking on the button will cause the text to go to lowercase.

<TextBox Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Column="0" />
<Button Content="Make Lower" Commands:Click.Command="{Binding MakeLowercase}" Grid.Column="1" />

Next is the ViewModel in its pure (no abstractions) form:

public class MainPageViewModel : INotifyPropertyChanged
{
    public MainPageViewModel()
    {
        MakeLowercase = new DelegateCommand<pobject>(ExecuteMakeLowercase, CanExecuteMakeLowercase);
    }

    private void ExecuteMakeLowercase(object obj)
    {
        Text = Text.ToLower();
    }

    private bool CanExecuteMakeLowercase(object arg)
    {
        return !string.IsNullOrEmpty(Text);
    }

    private string _text;
    public string Text
    {
        get { return _text; }
        set
        {
            _text = value;
            FirePropertyChanged("Text");
            MakeLowercase.RaiseCanExecuteChanged();
        }
    }

    private DelegateCommand<object> _makeLowercase;
    public DelegateCommand<object> MakeLowercase
    {
        get { return _makeLowercase; }
        set
        {
            _makeLowercase = value;
            FirePropertyChanged("MakeLowercase");
        }
    }

    protected void FirePropertyChanged(string propertyName)
    {
        var handlers = PropertyChanged;
        if (handlers != null)
            handlers(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Problems with the traditional ViewModel implementation

  1. Lots of plumbing (Command in the constructor, PropertyChanged in property setters, ExecuteChanged evaluation in the Text setter, etc)
  2. Verbose properties (We can’t use auto-properties because of the need to notify of changes
  3. Unrelated events (Text property needs to know that CanExecuteMakeLowercase needs to be re-evaluated)
  4. INotifyPropertyChanged is error-prone due to string events
  5. Lots of redundancies makes maintenance messy

What a Rails-Inspired ViewModel might look like

public class MainPageViewModel : ActiveViewModel<MainPageViewModel.Properties>
{
    public enum Properties { Text }

    public void Execute_MakeLowercase()
    {
        Set(Properties.Text, Get<string>(Properties.Text).ToLower());
    }

    [DependentUpon(Properties.Text)]
    public bool CanExecute_MakeLowercase()
    {
        return !string.IsNullOrEmpty(Get<string>(Properties.Text));
    }
}

My goal was to reduce the amount of plumbing and redundancies in this code to communicate only what it needs to

  1. There is one property named Text
  2. The MakeLowercase command will act on the Text property and make it lowercase
  3. CanExecuteMakeLowercase will return true if Text has meaningful data
  4. CanExecuteMakeLowercase needs to be re-evaluated with Text changes

There is a lot of magic in ActiveViewModel.  I am using convention to define the properties as a list of enums (Properties).  The ActiveViewModel will generate these properties dynamically.  I am also using convention to create commands.  Any method that is prefixed with Execute_ will be made into a command property.  Any method prefixed with CanExecute_ will be evaluated in the same command.  Further, the CanExecute_ method can declare the properties that will cause the commands to re-evaluate, putting the dependency where it belongs – with the method that is dependant upon it!  Testability is really easy: Call the actions and validate the properties (via public Get()).  I didn’t implement it, but actions based on property setters could very easily use the DependentUpon attribute to avoid INotifyPropertyChanged chaining that can get quite ugly.

Summary

I think this approach has a lot of potential.  I am posting it in order to move the conversation forward.  When the MVVM dust settles, and we have some best practices flushed out, what do we want our ViewModels to look like?  Even though I consider this class experimental and exploratory (not meant to be used in production), I feel compelled to call out some weaknesses that will (or may) need to be addressed for a more production-ready base class:

  1. The ActiveViewModel class will not work in Silverlight.  It relies heavily on custom type descriptors which are not available in Silverlight.  Hopefully, in Silverlight 4.0, we will have some better support for dynamic property generation.  This may be in the form of C# 4.0 (with the DynamicObject.Try[SG]etMember overrides, for instance), property descriptors, or something else (better IronRuby support, perhaps?)
  2. There is not a lot of type safety with the properties.  They are stored internally as plain objects.  The Get method lets you get at a type-casted value, but you need to know it when you ask for it.  We might change the property declaration from an enum to a list of name/type pairs and enforce some better type safety in the base class?
  3. Because there are not properties, we loose “equals semantics”.  Get/Set is harder to read/follow than simply assigning and reading properties

Finally, in case you are curious, you can see my implementation (at the time of this post) of the ActiveViewModel from my Launchpad project.


Friday, September 18, 2009 #

Shout it kick it on DotNetKicks.com

DynamicWrapper project on CodePlex

Edit: DynamicWrapper does not work in SIlverlight as I first though.  My unit tests passed, but in runtime I get an exception when I try to use the class.  I will be looking at some alternatives.

Over the past few weeks, I have been working on a utility that I have wanted for years: something that allows me to apply an interface to an object that matches the contract but doesn’t actually implement the interface.  In other words, I’ve wanted duck typing in C#.  The code and project can be found on CodePlex.  It is set up so you simply copy one file into your solution and use the extension methods.

Why did I want this?  Because I write a lot of unit tests and I develop in .Net with C#.  Because I write way too many wrapper classes to make my code testable.  For example, lets say that I have a class that I want to test and it acts upon a framework object:

public sealed class FrameworkClass
{
    internal FrameworkClass() {}
    
    public int X {get; set;}
    public int Y {get; set;}
    public int Calculate() { return DoSomeStuff(); }
}
public class MyClass
{
    public void DoSomethingWithFrameworkData(FrameworkClass value)
    {
        // Do Something
    }
}

The problem is that I can’t test MyClass because it is dependent upon FrameworkClass which I can never construct myself (it is sealed with an internal constructor and no interface).  The solution for this is simple but tedious – create a wrapper class that implements an interface and proxy through the wrapper class to the real object.  This approach works, but I can say this: I am sick of writing wrapper classes!

This is why I created this DynamicWrapper utility.  It exposes two extension methods: realObject.As<Interface>() and wrapper.AsReal<ConcreteClass>().  It uses Reflection to emit a dynamically generated wrapper class that implements the interface, and wraps your object for you.  It sounds complicated, but it is extremely simple to use.

Here is an example. Start by creating an interface that looks like the FrameworkClass:

public interface ICalculatable
{
    int X {get; set;}
    int Y {get; set;}
    int Calculate();
}

Modify your class to depend on ICalculatable:

public void DoSomethingWIthFrameworkData(ICalculatable value) {}

Now, when you pass the framework class into the MyClass, you can wrap it with the interface:

myObject.DoSomethingWithFrameworkData(frameworkObject.As<ICalculatable>());

If you need the framework object to pass back to the framework, it is really simple:

wrapper.AsReal<FrameworkClass>()

That’s all there is to it!  The utility is very simple.  It just gets me out of the business of writing (and maintaining) wrapper classes. I am now free to get back to real development.

*On a slightly related note, I will be focusing my learning efforts towards Ruby in the coming months.*


Thursday, August 27, 2009 #

More Adventures in MVVM Shout it kick it on DotNetKicks.com

One of the biggest points of friction for me when implementing the MVVM pattern happens when I need to bind commands to events.  When using Prism, I get the Button.Click command binding out of the box, but every other event needs to be wired up individually.  Doing this requires a LOT of boilerplate code that is very easy to get wrong.  In my last post, I published some code to alleviate that pain.  Still, it requires you to write a new behavior and attachment for every event that you want to bind an event to.

For a while now, I have toyed with the idea of just binding commands to events directly.  I ran into a lot of bumps in the road.  For instance, every event handler has a different event argument type.  This requires all of the handlers to be dynamic.  I also couldn’t create an inline command binding – I will surely want to bind more than one event per control – so I need to create a collection of bindings.  Creating arrays of structures created its own troubles – binding only works with FrameworkElements within the visual tree.  This required me to write my own crude binding within my generic behavior.

What follows is very loosely based off of the Chinch MVVM framework.  I tested this code in Silverlight and WPF and it works really well!

Assume I have a ViewModel that looks like this:

public class MainPageViewModel : INotifyPropertyChanged
{
    ...
    public ICommand MouseLeaveCommand { get; private set; }
    public ICommand MouseEnterCommand { get; private set; }
    public ICommand ClickCommand { get; private set; }
    ...
}

I can then bind the commands to events on a control (Button, for instance):

<Button Content="Click Me">
    <Behaviors:Events.Commands>
        <Behaviors:EventCommandCollection>
            <Behaviors:EventCommand CommandName="MouseEnterCommand" EventName="MouseEnter" />
            <Behaviors:EventCommand CommandName="MouseLeaveCommand" EventName="MouseLeave" />
            <Behaviors:EventCommand CommandName="ClickCommand" EventName="Click" />
        </Behaviors:EventCommandCollection>
    </Behaviors:Events.Commands>
</Button>

I no longer need to write any extra code whenever I want to attach commands to my events!  There are a few caveats to this code:

  1. The XAML requires the EventCommandCollection to be declared in the XAML.  I struggled to figure out how to eliminate this but gave up.  Someone smarter than me might be able to tell me what I am doing wrong.
  2. This code does not consider command properties.  Every command assumes a null parameter.  If you need parameters (like data context), then you’ll have to do something differently (either use the old-school mechanism or extend this code to handle some special event types).
  3. You don’t bind directly to the command.  Instead, you declare the name of the command (Notice CommandName is not bound).  The behavior binds for you using a primitive mechanism.

Here is the command behavior that does all the work:

public class Events
{
    private static readonly DependencyProperty EventBehaviorsProperty =
        DependencyProperty.RegisterAttached(
        "EventBehaviors",
        typeof(EventBehaviorCollection),
        typeof(Control),
        null);

    private static readonly DependencyProperty InternalDataContextProperty =
        DependencyProperty.RegisterAttached(
        "InternalDataContext",
        typeof(Object),
        typeof(Control),
        new PropertyMetadata(null, DataContextChanged));

    private static void DataContextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var target = dependencyObject as Control;
        if (target == null) return;

        foreach (var behavior in GetOrCreateBehavior(target))
            behavior.Bind();
    }

    public static readonly DependencyProperty CommandsProperty =
        DependencyProperty.RegisterAttached(
        "Commands",
        typeof(EventCommandCollection),
        typeof(Events),
        new PropertyMetadata(null, CommandsChanged));

    public static EventCommandCollection GetCommands(DependencyObject dependencyObject)
    {
        return dependencyObject.GetValue(CommandsProperty) as EventCommandCollection;
    }

    public static void SetCommands(DependencyObject dependencyObject, EventCommandCollection eventCommands)
    {
        dependencyObject.SetValue(CommandsProperty, eventCommands);
    }

    private static void CommandsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var target = dependencyObject as Control;
        if (target == null) return;

        var behaviors = GetOrCreateBehavior(target);
        foreach (var eventCommand in e.NewValue as EventCommandCollection)
        {
            var behavior = new EventBehavior(target);
            behavior.Bind(eventCommand);
            behaviors.Add(behavior);
        }

    }

    private static EventBehaviorCollection GetOrCreateBehavior(FrameworkElement target)
    {
        var behavior = target.GetValue(EventBehaviorsProperty) as EventBehaviorCollection;
        if (behavior == null)
        {
            behavior = new EventBehaviorCollection();
            target.SetValue(EventBehaviorsProperty, behavior);
            target.SetBinding(InternalDataContextProperty, new Binding());
        }

        return behavior;
    }
}

public class EventCommand
{
    public string CommandName { get; set; }
    public string EventName { get; set; }
}

public class EventCommandCollection : List<EventCommand>
{
}

public class EventBehavior : CommandBehaviorBase<Control>
{
    private EventCommand _bindingInfo;

    public EventBehavior(Control control)
        : base(control)
    {

    }

    public void Bind(EventCommand bindingInfo)
    {
        ValidateBindingInfo(bindingInfo);

        _bindingInfo = bindingInfo;

        Bind();
    }

    private void ValidateBindingInfo(EventCommand bindingInfo)
    {
        if(bindingInfo == null) throw new ArgumentException("bindingInfo");
        if (string.IsNullOrEmpty(bindingInfo.CommandName)) throw new ArgumentException("bindingInfo.CommandName");
        if (string.IsNullOrEmpty(bindingInfo.EventName)) throw new ArgumentException("bindingInfo.EventName");
    }

    public void Bind()
    {
        ValidateBindingInfo(_bindingInfo);
        HookPropertyChanged();
        HookEvent();
        SetCommand();
    }

    public void HookPropertyChanged()
    {
        var dataContext = TargetObject.DataContext as INotifyPropertyChanged;
        if (dataContext == null) return;

        dataContext.PropertyChanged -= DataContextPropertyChanged;
        dataContext.PropertyChanged += DataContextPropertyChanged;
    }

    private void DataContextPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == _bindingInfo.CommandName)
            SetCommand();
    }

    private void SetCommand()
    {
        var dataContext = TargetObject.DataContext;
        if (dataContext == null) return;

        var propertyInfo = dataContext.GetType().GetProperty(_bindingInfo.CommandName);
        if (propertyInfo == null) throw new ArgumentException("commandName");

        Command = propertyInfo.GetValue(dataContext, null) as ICommand;
    }

    private void HookEvent()
    {
        var eventInfo = TargetObject.GetType().GetEvent(
            _bindingInfo.EventName, BindingFlags.Public | BindingFlags.Instance);
        if (eventInfo == null) throw new ArgumentException("eventName");

        eventInfo.RemoveEventHandler(TargetObject, GetEventMethod(eventInfo));
        eventInfo.AddEventHandler(TargetObject, GetEventMethod(eventInfo));
    }

    private Delegate _method;
    private Delegate GetEventMethod(EventInfo eventInfo)
    {
        if (eventInfo == null) throw new ArgumentNullException("eventInfo");
        if (eventInfo.EventHandlerType == null) throw new ArgumentException("EventHandlerType is null");

        if (_method == null)
        {
            _method = Delegate.CreateDelegate(
                eventInfo.EventHandlerType, this,
                GetType().GetMethod("OnEventRaised",
                BindingFlags.NonPublic | BindingFlags.Instance));
        }

        return _method;
    }

    private void OnEventRaised(object sender, EventArgs e)
    {
        ExecuteCommand();
    }
}

public class EventBehaviorCollection : List<EventBehavior>
{ }

Friday, August 21, 2009 #

More Adventures in MVVM  Shout it kick it on DotNetKicks.com

There are several examples on the web that describe the “Attached Behavior” pattern in Silverlight and WPF.  This pattern works really well for binding commands in the ViewModel to controls in the View.  The problem with this is that for every behavior, there is a LOT of boilerplate code that goes along with it.  Because the DepencencyProperties need to be static, they cannot be easily abstracted into a common class. 

If you want to attach a MouseEnterBehavior to a control, you need to create two or three static Dependency Properties in the MouseEnter class.  They are MouseEnter.Command, MouseEnter.MouseEnterBehavior and optionally, MouseEnter.CommandParameter.

    public class MouseEnter 
    {
        private static readonly DependencyProperty BehaviorProperty =
            DependencyProperty.RegisterAttached(
                "MouseEnterBehavior",
                typeof(MouseEnterBehavior),
                typeof(Control),
                null);

        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached(
                "Command",
                typeof(ICommand),
                typeof(MouseEnter),
                new PropertyMetadata(OnSetCommand));

        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.RegisterAttached(
                "CommandParameter",
                typeof(object),
                typeof(MouseEnter),
                new PropertyMetadata(OnSetParameter))

And then the "Change Handlers"

        private static void OnSetCommand(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
        {
            var target = dependencyObject as Control;
            if (target == null)
                return;

            GetOrCreateBehavior(target).Command = args.NewValue as ICommand;
        }

        private static void OnSetParameter(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
        {
            var target = dependencyObject as Control;
            if (target != null)
            {
                GetOrCreateBehavior(target).CommandParameter = args.NewValue;
            }
        }

        protected static MouseEnterBehavior GetOrCreateBehavior(Control control)
        {
            var behavior = control.GetValue(BehaviorProperty) as MouseEnterBehavior;
            if (behavior == null)
            {
                behavior = new MouseEnterBehavior(control);
                control.SetValue(BehaviorProperty, behavior);
            }

            return behavior;
        }

Since the Dependency Properties are static, Silverlight also requires you to in include Get* and Set* static methods:

        public static void SetCommand(Control control, ICommand command) { control.SetValue(CommandProperty, command); }
        public static ICommand GetCommand(Control control) { return control.GetValue(CommandProperty) as ICommand; }
        public static void SetCommandParameter(Control control, object parameter) { control.SetValue(CommandParameterProperty, parameter); }
        public static object GetCommandParameter(Control buttonBase) { return buttonBase.GetValue(CommandParameterProperty); }

This is a classic case of reuse via “Copy and Paste”.  The problem is that there are several places in this code where you need to change three different types and many strings.  If you don’t invoke the magic incantation properly, nothing works.  It will compile but it won’t work (or you will get an obscure XAML parse error).

I cringe whenever I have to employ copy/paste reuse.  In the cases where it is absolutely necessary (such as this), I believe the risk can be reduced proportionately to the complexity of the modification after you paste.  This is why I came up with an Attachment base class to generalize all of this boilerplate code.  The previous code can be reduced to:

    public class MouseEnter : Attachment<Control, MouseEnterBehavior, MouseEnter>
    {
        private static readonly DependencyProperty BehaviorProperty = Behavior();
        public static readonly DependencyProperty CommandProperty = Command(BehaviorProperty);
        public static readonly DependencyProperty CommandParameterProperty = Parameter(BehaviorProperty);

        public static void SetCommand(Control control, ICommand command) { control.SetValue(CommandProperty, command); }
        public static ICommand GetCommand(Control control) { return control.GetValue(CommandProperty) as ICommand; }
        public static void SetCommandParameter(Control control, object parameter) { control.SetValue(CommandParameterProperty, parameter); }
        public static object GetCommandParameter(Control buttonBase) { return buttonBase.GetValue(CommandParameterProperty); }
    }

The only modifications to this copied code exist on the first line. 

What is the class name?  MouseEnter (2 places)
What type of control can the behavior attach to? Control
What type of behavior do you want to attach? MouseEnterBehavior

In addition to the decreased configuration complexity, the actual code that needs to be copied goes from 58 lines of boilerplate code to 11 lines of boilerplate code.  This is a big win, in my opinion.

In this code, I am using the CommandBehaviorBase class from the Prism framework.  It is part of the generic constraints.  If you use something else for your behaviors, replace it as you see fit.  Your own base class for command behaviors would slip in nicely, I am sure.

Here is the Attachment base class:

    public class Attachment<TargetT, BehaviorT, AttachmentT>
        where TargetT : Control
        where BehaviorT : CommandBehaviorBase<TargetT>
    {
        public static DependencyProperty Behavior()
        {
            return DependencyProperty.RegisterAttached(
                typeof(BehaviorT).Name,
                typeof(BehaviorT),
                typeof(TargetT),
                null);
        }

        public static DependencyProperty Command(DependencyProperty behaviorProperty)
        {
            return DependencyProperty.RegisterAttached(
                "Command",
                typeof (ICommand),
                typeof(AttachmentT),
                new PropertyMetadata((target, args) => OnSetCommandCallback(target, args, behaviorProperty)));
        }

        public static DependencyProperty Parameter(DependencyProperty behaviorProperty)
        {
            return DependencyProperty.RegisterAttached(
                "CommandParameter",
                typeof (object),
                typeof (AttachmentT),
                new PropertyMetadata((target, args) => OnSetParameterCallback(target, args, behaviorProperty)));
        }

        protected static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e, DependencyProperty behaviorProperty)
        {
            var target = dependencyObject as TargetT;
            if (target == null)
                return;

            GetOrCreateBehavior(target, behaviorProperty).Command = e.NewValue as ICommand;
        }

        protected static void OnSetParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e, DependencyProperty behaviorProperty)
        {
            var target = dependencyObject as TargetT;
            if (target != null)
            {
                GetOrCreateBehavior(target, behaviorProperty).CommandParameter = e.NewValue;
            }
        }

        protected static BehaviorT GetOrCreateBehavior(Control control, DependencyProperty behaviorProperty)
        {
            var behavior = control.GetValue(behaviorProperty) as BehaviorT;
            if (behavior == null)
            {
                behavior = Activator.CreateInstance(typeof(BehaviorT), control) as BehaviorT;
                control.SetValue(behaviorProperty, behavior);
            }

            return behavior;
        }
    }

And finally, just to complete the example, here is what the MouseEnterBehavior looks like:

    public class MouseEnterBehavior : CommandBehaviorBase<Control>
    {
        public MouseEnterBehavior(Control selectableObject)
            : base(selectableObject)
        {
            selectableObject.MouseEnter += (sender, args) => ExecuteCommand();
        }
    }

And to use it in your XAML, it would look like this:

<Button Behaviors:MouseEnter.Command="{Binding MouseEnter}" Behaviors:MouseEnter.CommandParameter="Optional Paremeter"/> 

Friday, August 07, 2009 #

More Adventures in MVVM

It has been a while since I have posted.  With CodeStock, GiveCamp, Vacation, overtime at work and my other speaking gigs, I have been very busy.  But things are calming down.  I have several posts I’d like to get out, but for the time being, I thought I would post my conversation with David Giard about the MVVM pattern:


Friday, June 19, 2009 #

More Adventures in MVVM Shout it kick it on DotNetKicks.com

imageA demo that I added to my MVVM talk is one that compares a “Ball of Mud” application with a componentized MVVM application with the exact same set of features.  I do this to contrast a messy, un-testable work of code to a cleanly separated, testable work.  The application I chose to write is a Twitter search application in WPF.  When you download the code, you will see two folders: “BallOfMud” and “MVVM”. 

The “Ball of Mud” app includes the entire app in a XAML file and a code-behind.  The code is incredibly dense… it does a TON of stuff, all in one page of code.  Unfortunately, is practically un-testable.  Even if you could test it, the code hits a live twitter.com.  Not the way you want to write tests.  This way of writing software works well for demos, but it certainly does not scale to real-life applications.

The MVVM example, on the other hand, is significantly broken up into components (4 layers).  There are 2 Views (TwitterSearchView and TweetView) with 2 corresponding ViewModels.  Then, there is a Model layer which is responsible for parsing data that comes from the Service layer into “Tweets”.  There is more code than the “Ball of Mud” example, but the code is testable, and modular.  You can swap out different services or models, if you wish.  In fact, in the Model layer, you will find a “CannedData” class that I use when I don’t have an internet connection when I give my presentation.  It just swaps in.  This example might feel like “overkill”, but as the application grows in scope, this architecture will scale exceptionally well.

Twitter Search “Ball of Mud” vs “MVVM”


Friday, June 12, 2009 #

More Adventures in MVVM

Shout it kick it on DotNetKicks.com

Yesterday, I gave my MVVM talk to the public for the first time in Flint, MI.  I will be in Southfield next week and Tennessee the week after that (CodeStock), giving the same talk.  Although I have some changes to make, I thought I would post what I presented last night.  I will probably work on a smaller example that I will also put up here when I am done with it.

The Demo

The demo is a front-end to a recipe database.  It should compile and run out of the box.  It was designed to work against www.eCuisine.com, but it requires you to sign up with them in order to get real data.  To get around that, I have stored some “canned” recipes in the service by default.  If you want to hook it up to use the real eCuisine.com service, simply register with them from www.eCuisine.com and add your email/client ID in the eCuisine.svc.cs file and uncomment the null for the service.  If you don’t do that, everything still works well enough for you to get the feel for the app.

The vast majority of the UI behavior exists in the View-Models and I show a few different approaches to getting View-Models hooked up to the views.

There is also a full suite of tests.  Be sure to check them out for ideas to how you might test your View-Models.

Demo Code

Powerpoint Slides