Friday, 21 March 2008

Very simple ICommand implementation for Silverlight

One thing lacking the current Silverlight Beta 2 release is an ICommand implementation. "Commanding" is one of my favourite features of WPF. The idea is that any command source (such as a button) can be bound to a command and that command will be executed whenever the command source is activated (e.g. the button is clicked).

WPF's ICommand interface features the following three members:

Execute(object parameter) - Called whenever the command is activated. The parameter is optional.

CanExecute(object parameter) - This method is called to determine whether the command can execute at the current time. The main feature of this is the command source can disable itself if its command cannot be executed.

event CanExecuteChanged - The command should raise this event whenever it's ability to be executed has changed.

One advantage of commands over standard event handlers is that they allow you to place your event handling implementation outside of your "code behind" class and handle commands in a more generic fashion. This is a key part of implementing the Model-View-ViewModel pattern, which I am trying to implement for my Silverlight application (more to follow on this).

Note that WPF takes commanding a step further than just the ICommand interface, providing us with the RoutedCommand implementation. I won't go into detail about Routed Command here, as Josh Smith already has a great post about them, in which you will understand the advantages of using them over standard ICommands.

Anyway, I digress... back to Silverlight! The important thing here is that I wanted to use commands when developing for Silverlight, and there is nothing available. I made the choice to knock something together very quickly to solve this issue, making use of Attached Properties to bind the commands source (currently only ButtonBase derivatives are supported) to ICommand implementations. I could have spent A LOT more time on this, but I figure that commands are such a key part of WPF that they will soon make their way into Silverlight rendering my code fairly redundant!

I decided to place my code into a Silverstone (random name I know!) assembly, which you can download here. Add the project to your solution and compile it. Now lets create a simple command which just alerts a message:

using System;

using System.Windows.Browser;

 

using Mosafi.Silverlight;

 

namespace WindowsApplication1

{

    public class TestCommand : ICommand

    {

        public event EventHandler CanExecuteChanged;

 

        public bool CanExecute(object parameter)

        {

            return true;

        }

 

        public void Execute(object parameter)

        {

            HtmlPage.Window.Alert("The TestCommand was Executed");

        }

    }

}

That's the command defined, now we need to create an instance somewhere. One would often place all related commands in a single static class, and reference them in XAML using the {x:Static} markup extension. However Silverlight doesn't have this extension, so we will put them in the Resources and use the {StaticResource} markup extension instead. Here is how to create a page with a button which executes the command when clicked:

<UserControl x:Class="WindowsApplication1.Page"

   xmlns="http://schemas.microsoft.com/client/2007"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:mosafi="clr-namespace:Mosafi.Silverlight;assembly=Mosafi.Silverlight"

   xmlns:WindowsApplication1="clr-namespace:WindowsApplication1">

 

    <UserControl.Resources>

        <WindowsApplication1:TestCommand x:Key="TestCommand" />

    </UserControl.Resources>

 

    <Button Content="Execute Test Command"

            Width="100"

            HorizontalAlignment="Left"

            mosafi:CommandBinder.Command="{StaticResource TestCommand}" />

</UserControl>

DISCLAIMER: In no way is this a fully featured implementation of Commanding, and I would not recommend using it in a "production" system (the reason being that the command handlers may hold onto the buttons indefinitely and stop them from being garbage collected). However it should make the transition to any forthcoming Microsoft command implementation much easier.

Any feedback much appreciated.

Hope this help

Neil

UPDATE: This code has been moved into the Silverstone framework

6 comments:

Josh Smith said...

Great start, Neil. This is a very forward-thinking post.

Thanks,
Josh Smith
http://joshsmithonwpf.wordpress.com

Neil Mosafi said...

Thanks for the feedback Josh. Believe me it means a lot!

Neil

Anonymous said...

There are some errors when I compiled your code with Silverlight 2 beta2.

Here are the things to do if you wanna compile your code with Silverlight 2 beta2.

1) Remove System.Windows.Controls.dll

2) Go to CommandBinder class and change this

public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command",
typeof(ICommand), typeof(CommandBinder), new CommandManager.HandleCommandPropertyChanged);

to this code.

public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command",
typeof(ICommand), typeof(CommandBinder), new PropertyMetadata(CommandManager.HandleCommandPropertyChanged));

Michael Sync said...

The previous comment is written by me but i forget to put my name.. sorry!

Neil Mosafi said...

Hi Michael

Thanks for the feedback. I should have updated the post but this code is all now in the Silverstone library which you can get at http://silverstone.googlecode.com. I made the fixes for Silverlight 2 Beta 2 a while ago.

I will update the post now, thanks.

generic cialis 20mg said...

Hello, I do not agree with the previous commentator - not so simple