Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ICommand convinient implementation for MVVM pattern

0.00/5 (No votes)
11 Jun 2015 1  
Implementation if ICommand is trivial, but it is poor by its nature. We can not get Picture or Text or Disabled properties from usual ICommand implementation. But we can make a trik and have all information about command in a single object and use this information on as many command elements as we w

Introduction

The main idea of tip is to make work with command more convinient in following:

  1. Command should be selfdescriptive and have description, tooltips, icons in itselt.
  2. It could be simply used with MWWM pattern.
  3. XAML should be as simple as possible.

Background

This article is a continuation of article previously posted http://www.codeproject.com/Tips/989373/INotifyPropertyChanged-convinient-implementation, because it uses code from it.

Using the code

To make work with commands simpler we should do following:

  1. Create class with will encapsulate all command properties and will implement ICommand interface.
  2. Create styles for different UI elements: buttons, menu buttons
  3. Combine all of that on the view.

Here is the implementation of Command (if you downloaded source code you already have it):

Download Command.zip

And example of command instance definition:

CommandA = new CommandT(
    o =>
    {
        Status = "Command A Executing";
        for (int i = 0; i < 10; i++)
        {
            Status = "Left to be disabled: {0}s".F(10 - i);
            Thread.Sleep(1000);
        }
                   
    },
    o=>true,
    err =>
    {
        this.ShowMessageBox(err.Message, err.StackTrace, MessageBoxButton.OK, MessageBoxImage.Error);
    },
    "Command A",
    "Command A My long description",
    R.TryGetImageSource("A"),
    true);

Now we should create some styles, wich will use Command properties:

<!--Base style of command button-->
<Style TargetType="Button" x:Key="Buttons_CommandButtonBase" BasedOn="{StaticResource Common_ToolTipedElement}">
    <Setter Property="we:ImageButtonExtension.ImageSource" Value="{Binding RelativeSource={RelativeSource Self}, Path=Command.Image}" />
    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Command.ToolTip}" />
    <Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource Self}}" />
    <Setter Property="Visibility">
        <Setter.Value>
            <MultiBinding Converter="{StaticResource Converters_ObjectBooleanToVisibility}">
                <Binding RelativeSource="{RelativeSource Self}" Path="Command" />
                <Binding RelativeSource="{RelativeSource Self}" Path="Command.IsVisible" />
            </MultiBinding>
        </Setter.Value>
    </Setter>
</Style>

As you can see, Command - is view model to wich we make bindings, so UI will reflect to command properties changing.

Behind the scene there are many additional code (you can see it in test project), but our final view will be simple:

 <StackPanel DataContext="{StaticResource VM}">
    <GroupBox Header="Menu">
        <Menu>
            <MenuItem Command="{Binding CommandA}" Style="{StaticResource MenuButtons_BaseWithCommand}" />
            <MenuItem Command="{Binding CommandB}" Style="{StaticResource MenuButtons_BaseWithCommand}" />
            <MenuItem Header="Commands">
                <MenuItem Command="{Binding CommandA}" Style="{StaticResource MenuButtons_BaseWithCommand}" />
                <MenuItem Command="{Binding CommandB}" Style="{StaticResource MenuButtons_BaseWithCommand}" />
            </MenuItem>
        </Menu>
    </GroupBox>
       
    <GroupBox Header="Buttons" command:Command.DisableTarget="True">
        <StackPanel>
            <Button Command="{Binding CommandA}" Style="{StaticResource Buttons_BaseTextButtonWithCommand}"/>
            <Button Command="{Binding CommandA}" Style="{StaticResource Buttons_BaseImageButtonWithCommand}"/>
            <Button Command="{Binding CommandB}" Style="{StaticResource Buttons_BaseTextButtonWithCommand}"/>
            <Button Command="{Binding CommandB}" Style="{StaticResource Buttons_BaseImageButtonWithCommand}"/>
        </StackPanel>
    </GroupBox>
       
    <TextBlock Text="{Binding Status}" />
</StackPanel>

And final picture will look like this:

As you can see, everithing works on bindings (Icons, ToolTips, Headers)...

In the ViewModel we have just two commands, but we simply bind them to eight UI elements (buttons and menu buttons).

Test project contains several useful extensions and styles examples, they are simple so I will not type text too much, just try it...

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here