I’m a big fan of the MVVM Pattern for Silverlight development, so naturally I was excited about Silverlight 4 having support for Commanding.  I recently upgraded my current project to Silverlight 4 and I found that binding my buttons to my View Model commands was pretty easy.  However, it wasn’t long before I needed to create a custom control and I wasn’t sure how the Command Binding would work.  I searched the web for some samples but found none so I was on my own.  It wasn’t too hard to figure out the solution, here is how I did it.

The setup… For the sake of this demo, I’ll need a resuable control that combines 2 buttons:  Save and Cancel.  I’ll call it a SaveCancel control :).  The control is simple enough.  Thanks to Silverlight 4, buttons already support the command binding – all you have to do is bind the command in your View Model to the Command property of the button (and optionally the CommandParameter property).  If you aren’t familiar with the basics of commanding, I suggest you check out this blog post by John Papa.  Anyway, when it is time to use the SaveCancel control on another page/control, it becomes pretty clear that you can’t access the individual button’s properties to bind to them!  The individual buttons are not publicly available since they are “child” controls of the SaveCancel control.  The solution:  The Command and CommandParameter properties of each button are just DependencyProperties so all you have to do is create matching properties on the new control that “wrap” the internal properties.

Here’s how it’s done…

First, the XAML of the SaveCancel control is pretty straightforward:

<UserControl x:Class="CustomControlWithCommanding.SaveCancel"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" >
    
    <StackPanel x:Name="LayoutRoot" Orientation="Horizontal" >
        <Button x:Name="Save" Width="50" Height="25" Content="Save" Margin="0,0,5,0" />
        <Button x:Name="Cancel" Width="50" Height="25" Content="Cancel" />
    </StackPanel>
</UserControl>

Next the Code Behind of the SaveCancel control.  Here is where all of the wiring is done for each button’s commands. There are a few parts.  First is the DependencyProperty for the Save button’s command.  Like any dependency property, you need a public property with a Get/Set that sets the value of the Dependency Property as well as a DependencyProperty:

public ICommand SaveCommand
{
    get { return (ICommand)GetValue(SaveCommandProperty); }
    set { SetValue(SaveCommandProperty, value); }

}
public static readonly DependencyProperty SaveCommandProperty =
    DependencyProperty.Register("SaveCommand", typeof(ICommand), typeof(SaveCancel), 
                                new PropertyMetadata(null, OnSaveCommandChanged));

Note that in the PropertyMetaData argument for the SaveCommandProperty we are passing in a callback reference (OnSaveCommandChanged).  We’ll use that method to set the value of the new DependencyProperty to the actual Save button.  Here is the code:

private static void OnSaveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    SaveCancel sc = (SaveCancel)d;
    sc.Save.Command = (ICommand)e.NewValue;
}

To be complete, we’ll do some similar work to make sure that we can wire up the CommandParameter to the Save button as well, even though we don’t really need it to make the button work for this sample.  

public object SaveCommandParameter
{
    get { return GetValue(SaveCommandParameterProperty); }
    set { SetValue(SaveCommandParameterProperty, value); }

}

public static readonly DependencyProperty SaveCommandParameterProperty =
    DependencyProperty.Register("SaveCommandParameter", typeof(object), typeof(SaveCancel), 
        new PropertyMetadata(null, OnSaveCommandParameterChanged));

private static void OnSaveCommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    SaveCancel sc = (SaveCancel)d;
    sc.Save.CommandParameter = e.NewValue;
}

To use the new SaveCancel control in another Silverlight control, all I need is some code like the sample below.  It works perfectly with no events wired up and no code behind on the page where it is used!

<CustomControlWithCommanding:SaveCancel SaveCommand="{Binding SaveCommand}" 
                                        CancelCommand="{Binding CancelCommand}" />

Of course, my ViewModel must have the commands (SaveCommand and CancelCommand) to support this as well.  But that is just normal ViewModel commanding.  Again, if you aren’t familiar with that, check out John Papa’s blog post.

Complete Source Code:

To see the complete sample solution, download it here.

2 thoughts on “Creating Custom Silverlight 4 Controls That Support Command Binding

  1. Hi Schwammy

    Thanks for this nice article, you helped me a lot.
    Anyway I’ve got following question:
    I try to implement an own ICommand in my own UserControl. The UserControl owns a Textbox. If the user press ENTER, the ICommand should be raised.

    I implemented your "OnSaveCommandChanged"-method as follows:
    MyUserControl my = (myUserControl)d;
    my.myCommand = (ICommand)e.NewValue;

    When I try to raise the command over this.myCommand.Execute(null) I get an Exception, because myCommand is NULL.

    Can you help me to solve this problem?
    Thank you

    Reply

Leave a reply

required

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>