Click here to Skip to main content
15,885,278 members
Articles / Desktop Programming / WPF
Tip/Trick

ICommand convinient implementation for MVVM pattern

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
11 Jun 2015CPOL1 min read 5.7K   55   2  
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:

C#
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:

XML
<!--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:

XML
 <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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Saber Interactive
Russian Federation Russian Federation
My specializations:

C# (especially multithreading)
WPF (MVVM, styling)
WCF (message inspectors, configuration)
MSSQL (administartion, creation, procedures, recursive queries, bulk processing)

Comments and Discussions

 
-- There are no messages in this forum --