Silverlight has many things in common with WPF, but also many different or missing things because it is a “subset” of it.

One of the missing things is support for the ICommand interface (UPDATE: in Silverlight 2, this interface was included, but there is no implementation that uses it, so this post is still useful and the sample was updated to use Silverlight’s interface instead of my own copy of it from WPF). I find this interface (and the button’s behavior when bound to a command) extremely useful/necessary, especially when using DataTemplates bound to a Presentation Model (to provide the view for the model), as hooking events (like Click) is not an option in this scenario.

<Button Content=”Save” Command=”{Binding SaveOrderCommand}” />

As you might suspect, we (at p&p) are now spiking and seeing how the Composite Application Library for WPF (a.k.a. Prism or CompositeWPF) would work on Silverlight. One important part of the guidance provided is to use Commands for communication between the moving parts, and from the view (this is specially useful for testability).

Today the team published a small drop that contains some of the spikes we’ve been playing with, including an initial quick & dirt port of the library. We added the ICommand interface that is missing from WPF to the same System.Windows.Input namespace, not only to avoid adding new using statements all throughout the solutions, but in my opinion, because we hope Silverlight might support this out-of-the-box in the future, and we might be able to quickly switch to the provided implementation easily if they stay consistent with WPF’s API. (UPDATE: the interface is now part of Silverlight 2)

namespace System.Windows.Input
{
    public interface ICommand
    {
        bool CanExecute(object parameter);
        void Execute(object parameter);
        event EventHandler CanExecuteChanged;
    }
}

Once the ICommand interface is there, the DelegateCommand and CompositeCommand implementations included in CompositeWPF start working immediately and I can now call command.Execute(null) on my commands… big deal! But I want to hook my buttons to those commands from XAML!

public class DelegateCommand<T> : ICommand { … }

Well, how to hook to a command using XAML? easy: using attached behaviors. First, I need to define an attached property that will contain the command.

public static readonly DependencyProperty CommandProperty =
    DependencyProperty.RegisterAttached(“Command”, typeof(ICommand), typeof(Commands),
    new PropertyMetadata(CommandPropertyChanged));

Ok, I can attach the command to a button, but how will it be invoked when the button is clicked? Well, that’s when CommandPropertyChanged kicks in (and that’s why it’s an attached behavior, and not just a simple attached property):

private static void CommandPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    ButtonBase element = o as ButtonBase;
    if (element != null)
    {
        if (e.OldValue != null)
        {
            CommandButtonBehavior behavior = (CommandButtonBehavior)element.GetValue(CommandButtonBehaviorProperty);
            behavior.Detach();
            element.SetValue(CommandButtonBehaviorProperty, behavior);
        }
        if (e.NewValue != null)
        {
            CommandButtonBehavior behavior = new CommandButtonBehavior(element, (ICommand)e.NewValue));
            behavior.Attach();
            element.ClearValue(CommandButtonBehaviorProperty);
        }
    }
}

The code above creates an instance of a behavior class that contains the behavior. This instance is stored in a private attached property, in order to be able to retrieve the behavior and Detach it when unhooking the command (when e.OldValue is not null).

The following code shows how CommandButtonBehavior hooks to the Click event of the Button in order to invoke the command.

private class CommandButtonBehavior
{
    private readonly WeakReference elementReference;
    private readonly ICommand command;

    public CommandButtonBehavior(ButtonBase element, ICommand command)
    {
        this.elementReference = new WeakReference(element);
        this.command = command;
    }

    public void Attach()
    {
        ButtonBase element = GetElement();
        if (element != null)
        {
            element.Click += element_Clicked;
        }
    }

    public void Detach()
    {
        ButtonBase element = GetElement();
        if (element != null)
        {
            element.Click -= element_Clicked;
        }
    }

    private static void element_Clicked(object sender, EventArgs e)
    {
        DependencyObject element = (DependencyObject)sender;
        ICommand command = (ICommand)element.GetValue(CommandProperty);
        object commandParameter = element.GetValue(CommandParameterProperty);
        command.Execute(commandParameter);
    }

    private ButtonBase GetElement()
    {
        return elementReference.Target as ButtonBase;
    }
}

The reason for storing the button as a WeakReference, is to avoid the application from leaking memory when trying to destroy a view with a button that has not correctly unhooked the command.

Ok, I believe that this bunch of code might be helpful, but how to use it from XAML? Again, easy:

<Button Content=”Save” Commands:Commands.Command=”{Binding Path=SaveOrderCommand}” />

As you can see, this looks way too similar to how WPF commands are declared, except for the Commands:Commands part of it, because this is an attached property and not a direct dependency property of the Button class.

I’m attaching a sample that uses the classes published in Codeplex by the Prism team. The sample includes support for CommandParameter and allows enabling and disabling the button depending on whether the ICommand.CanExecute method returns true or false.

image

Note: Even if I’m using DelegateCommand, you could use your own implementation of ICommand, as the attached behavior is not coupled to any implementation of ICommand.

Disclaimer

This code is provided “AS IS” with no warranties, and confers no rights.

Download

You can get the sample with the attached behaviors from here (updated for SL 2 RTW), or you can download the code for the behaviors without the sample from the latest change set of the CompositeWPF source control, in the spikes folder.

More information

Nikhil Kothari has a great introduction and samples for attached behaviors on Silverlight here.

John Gossman blogs about attached behaviors on WPF (here and here).

Dave Relyea created a neat example of attached behavior on Silverlight here.

Ezequiel Jadib has more info on the spike published in Codeplex here.

Shout it

25 Responses to “ICommand for Silverlight with Attached Behaviors”

  1. Ezequiel Jadib’s Blog » Silverlight & Composite Application Guidance (Prism): Spike published Says:

    [...] not going into deep details on this because Julian Dominguez published a great post explaining how to use commands in [...]

  2. Joe's Blog Says:

    Building a Silverlight ComboBox Using Attached Behaviors…

    I recently needed to use a ComboBox in an application I was writing.  Because there is no built-in…

  3. Joe's Blog Says:

    Building a Silverlight ComboBox Using Attached Behaviors…

    I recently needed to use a ComboBox in an application I was writing.  Because there is no built…

  4. mhenderson Says:

    Thanks for this example. This is super helpful.

    How do you handle the situation where we have a control in the usercontrol that has overriden the datacontext, but we still want to bind to the usercontrol’s datacontext?

    I’m specifically talk about a DataGrid in the UserControl where the ItemsSource has been set. We want to have a command fire on an individual row, but cannot bind to the datacontext of the usercontrol because it is out of scope at that point.

    Any ideas?

    Thanks,
    Michael

  5. jdominguez Says:

    I’m glad you liked the example.
    Regarding the question, in Silverlight you cannot create a Binding with RelativeSource…
    Nevertheless, you could store the command in a Resource, and bind to it from the rows. You may have a problem with the timing there though, because Silverlight does not support DynamicResource either (just StaticResource).
    Let me know if this helps solve the problem.

  6. mhenderson Says:

    We thought about the resource, but that seems like added XAML overhead in declaring our commands (plus, I agree that there might be a timing issue). We’d like the wireing mechanism to be as terse as possible. Here’s what we ended up with:

    We’re using Presentation Model (M-V-VM) and IView is the root where we’re getting the DataContext containing the ICommands. We need to get the IView parent (or grandparent, great-grandparent, etc) from the ButtonBase. However, due to timing, the parent isn’t set when the Command is set, so we changed the Command attached property to be a string instead of an ICommand and store the value. Next, we subscribe to the ButtonBase loaded event, so that, on load, we walk up the FrameworkElement parent until we get to the IView and get it’s DataContext. Then we use reflection (from the stored command string) to get the appropriate ICommand on the DataContext and wire up the buttonbase click.

    Additionally, we can have tests that ensure all the wiring happens correctly. It seems to work well so far, plus we get to use reflection :)
    Any thoughts?

    Thanks!

  7. Jason Dolinger on Model-View-ViewModel » Lab49 Blog Says:

    [...] we can get the kind of Commanding that Jason uses in Silverlight as well. Check out the description here. Posted by dsimon in .Net, Featured Posts, Learning, Seminars, WPF / Digg this [...]

  8. Julian Dominguez’s Blog » ICommand for Silverlight 2.0 RTW Updated Sample Says:

    [...] time ago, we blogged about how to implement the ICommand feature that is available in WPF but missing in [...]

  9. Julian Dominguez’s Blog » Blog Archive » Prism V2’s drop 7 is out: Updates to Commanding and Modularity Says:

    [...] are following a similar approach to what we’ve done in a previous spike and blogged about it here, so I won’t go into many details about it in this [...]

  10. Building Infragistics Quince – UX Patterns Explorer - Andres Aguiar's Weblog Says:

    [...] app was built using Model-View-ViewModel with the same approach described by Julan Dominguez here. We also used the Prism EventAggregator. We did not have Prism for Silverlight at that time so we [...]

  11. MVVM pattern in Silverlight using SLEextensions Says:

    [...] http://blogs.southworks.net/jdominguez/2008/08/icommand-for-silverlight-with-attached-behaviors/ [...]

  12. Julian Dominguez’s Blog » Blog Archive » Prism 2.0 released: Composite Application Guidance for WPF and Silverlight – February 2009 Says:

    [...] in the RI). The basic idea around behaviors for ICommand is similar to what I blogged about in this post a while [...]

  13. MVVM notes and references | Corey Schuman Says:

    [...] http://blogs.southworks.net/jdominguez/2008/08/icommand-for-silverlight-with-attached-behaviors/#com... [...]

  14. Silverlight – Commands/Attached Behaviors… The Magic at { null != Steve } Says:

    [...] Check out Julian Dominguez’s blog post on ‘ICommand for Silverlight with Attached Behaviors’ [...]

  15. Damian Schenkelman’s Blog » Blog Archive » Commands with Attached Behavior for Silverlight 3 DataForm Says:

    [...] I checked the documentation and asked Julian Dominguez (the attached behavior guy), and Matias Woloski (an expert in the client development field) if attached behaviors was the way [...]

  16. Binary Bob’s Blog » My MVVM in Silverlight notes Says:

    [...] Julian Dominguez makes ICommand happen in Silverlight via attached behaviors here. [...]

  17. Damian Schenkelman’s Blog » Blog Archive » WebBrowser control Quickstart for the Composite Application Guidance for WPF and Silverlight (Prism-v2) Says:

    [...] a customer from the DataGrid is selected a command is executed (through an attached behavior with the DataGrid’s SelectionChanged event). This command publishes an event using the [...]

  18. Julian Dominguez’s Blog » Blog Archive » Presentation Model with DataTemplates in CompositeWPF (Prism) Sample Says:

    [...] this approach prematurely; if you need such a behavior, it could be easily solved by creating an attached behavior other than RegionManager.RegionName (BTW, this attached property IS an attached behavior…) [...]

  19. DotNetShoutout Says:

    ICommand for Silverlight with Attached Behaviors…

    Thank you for submitting this cool story - Trackback from DotNetShoutout…

  20. Damian Schenkelman’s Blog » Blog Archive » Learning Prism (Composite Application Guidance for WPF & Silverlight). How do I start? Says:

    [...] Southworks blogs: Julian, Ezequiel, Mariano, Matias. The post that is a MUST is Julian’s ICommand For Silverlight with Attached Behaviors. [...]

  21. MVVM Study Part 4: Naked WPF - .NET & Funky Fresh - Devlicio.us - Just the Tasty Bits Says:

    [...] methods.  (If you want to make this work in Silverlight 3.0, you are going to have to build a little more infrastructure.)  Here’s an example of how you would use it as part of a fictitious employee creation [...]

  22. Damian Schenkelman’s Blog » Blog Archive » Learning Prism (Composite Application Guidance for WPF & Silverlight) MVVM Fundamentals Says:

    [...] be understanding how do Commands with attached Behaviors work, a topic explained by Julian in this great post. After that you can use the code snippet I created some time ago to help you with the tedious task [...]

  23. Damian Schenkelman’s Blog » Blog Archive » Will Silverlight 4 ICommand support simplify using commands in Prism? Says:

    [...] other than Buttons do not have the possibility to bind their events to commands in the ViewModel, using attached behaviors is a good approach. You can use this code snippet to simplify the [...]

  24. Building a Silverlight ComboBox Using Attached Behaviors « joe.mcbride Says:

    [...] I recently needed to use a ComboBox in an application I was writing.  Because there is no built-in ComboBox in Silverlight I decided to explore building one using attached behaviors.  If you’re not familiar with this design pattern, check out Nikhil’s posts.  My ComboBox behavior is loosely based on his AutoComplete behavior.  I also make use of Julian’s ButtonCommands class, which he describes in this post. [...]

  25. Adventures in MVVM – Commands in Silverlight « Migration in progress Says:

    [...] I would have learned that that I learned attached behaviors wrong in the first place.  In Julian Dominguez’s blog post on the topic, he walks you through the thought process for attaching commands via behaviors.  Although this [...]

Leave a Reply