Commands in MVVM

http://s.codeproject.com/Articles/274982/Commands-in-MVVM


A consistent approach to Commands, Asynchronous Commands, and Events-to-Commands for WPF, Silverlight, and WP7.

Contents

  1. Example 1 - A Simple Command 
  2. Example 2 - A Simple Command Using Lambda Functions
  3. Example 3 - A Parameterized Command
  4. Example 4 - Enabling or Disabling a Command
  5. Example 5 - Commands that Fire Events
  6. Example 6 - An Asynchronous Command
  7. Example 7 - An Asynchronous Command that Updates the UI
  8. Example 8 - An Asynchronous Command that can be Cancelled
  9. Example 9 - Binding an Event to a Command
  10. How Does it Work - The Command Class
  11. How Does it Work - The Asynchronous Command Class
  12. How Does it Work - The Event Binding Class

Introduction

In this article I am going to describe how Commands work for projects that use MVVM (Model View View-Model). The approach I am describing works in exactly the same way whether you are using WPF, Silverlight, or Windows Phone 7. First, I will show a variety of ways that we can use commands in any MVVM project - this section works as a quick-reference for Commanding. Each example is then described in detail later on in the article - I will show exactly how the code works.

The code used is part of my Apex MVVM library, however as each section is described with full code examples, you can easily integrate these methods into existing projects or libraries - or simply add Apex as a reference and get started straight away.

Screenshot 1: Commanding in WPF

consistentmvvmcommands/WPF.png

Screenshot 2: Commanding in Silverlight

consistentmvvmcommands/SL.png

Screenshot 3: Commanding in Windows Phone 7

consistentmvvmcommands/WP7.png

What is a Command? 

This is a really critical concept in MVVM. Here's what you need to know.

A Command is an object that is bound to. It provides a separation between a user interface and logic.

This is the core concept. In a bit more detail we can describe a command as follows:

  1. A command is an object that implements the ICommand interface.
  2. Generally, it is associated with a function in some code.
  3. User interface elements bind to commands - when they are activated by the user the command is fired - which calls the associated function.
  4. Commands know if they are enabled or not.
  5. A function can disable the command object - automatically disabling any user interface elements associated with it. 
Actually, there's a whole lot more to Commands. We can use commands to deal with asynchronous functionality, to provide logic that can be tested with or without a user interface, and more.

Commanding Examples 

First we'll take a look at a set of scenarios where we will need to use commands. Each scenario has an associated details section later on in the article showing how it works. 

Important note: Every View Model in this set of examples contains an observable collection of strings named 'Messages' - each example application shows these messages in a list so that we can see what is happening. The base View Model is shown below:

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
    }

    private ObservableCollection<string> messages = new ObservableCollection<string>();

    public ObservableCollection<string> Messages
    {
      get { return messages; }
    }
}

My View Model is derived from 'ViewModel' which implements INotifyPropertyChanged, but you can use any View Model type or base that you like.

Example 1: A Simple Command Example

Requirement: I need to invoke a function of the View Model when a user interface element is pressed or activated.

The most simple example of a command is shown below. First, we add a 'Command' object to our View Model - with an associated function that will be called when the command is invoked:

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
      //  Create the simple command - calls DoSimpleCommand.
      simpleCommand = new Command(DoSimpleCommand);
    }

    /// <summary>
    /// The SimpleCommand function.
    /// </summary>
    private void DoSimpleCommand()
    {
      //  Add a message.
      Messages.Add("Calling 'DoSimpleCommand'.");
    }

    /// <summary>
    /// The simple command object.
    /// </summary>
    private Command simpleCommand;

    /// <summary>
    /// Gets the simple command.
    /// </summary>
    public Command SimpleCommand
    {
      get { return simpleCommand; }
    }
}

Now we bind the command to the 'Command' property of a button (or other UI element).

<Button Content="Simple Command" Command="{Binding SimpleCommand}" /> 

This is the most trivial example of a Command - we bind the Command object to the Command Dependency Property of an interface element. When the element is activated, the Command is invoked. Under the hood, this will cause the 'DoSimpleCommand' function to be invoked.

Example 1: How Does it Work?

Example 2: A Simple Command Example Using Lambda Expressions

Requirement: I need to invoke a function of the View Model when a user interface element is pressed or activated. However, it's such a simple function that I'd rather not have to write it out explicitly - can I use a lambda expression?

For all of the examples in this article, you can explicitly create a function, just as in Example 1, or you can use a lambda expression in-line. For small functions, a lambda expression can be a little tidier.

public MainViewModel()
{
      //  Create the lambda command, no extra function necessary.
      lambdaCommand = new Command(
        () =>
        {
          Messages.Add("Calling the Lamba Command - no explicit function necessary.");
        });
}

/// <summary>
/// The command object.
/// </summary>
private Command lambdaCommand;

/// <summary>
/// Gets the command.
/// </summary>
public Command LambdaCommand
{
  get { return lambdaCommand; }
} 

Now we bind the command to the 'Command' property of a button (or other UI element).

<Button Content="Lambda Command" Command="{Binding LambdaCommand}" /> 

What have we learnt? Anywhere we define a command, we can use either a named function or a lambda expression.

Example 2: How Does it Work?

Example 3: A Command with a Parameter

Requirement: When I invoke a command, I need to pass a parameter which has been set by a binding.

Anywhere we use a Command object (or an AsynchronousCommand object as we'll see later), we can optionally use a parameter with the function.

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
      //  Create the parameterized command.
      parameterizedCommand = new Command(DoParameterisedCommand);
    }

    /// <summary>
    /// The Command function.
    /// </summary>
    private void DoParameterisedCommand(object parameter)
    {
      Messages.Add("Calling a Parameterised Command - the Parameter is '" + 
                   parameter.ToString() + "'.");
    }

    /// <summary>
    /// The command object.
    /// </summary>
    private Command parameterizedCommand;

    /// <summary>
    /// Gets the command.
    /// </summary>
    public Command ParameterisedCommand
    {
      get { return parameterizedCommand; }
    }
}

Now we bind the command to the 'Command' property of a button (or other UI element), but also bind a parameter:

<Button Content="Parameterized Command" 
    Command="{Binding ParameterizedCommand}" CommandParameter={Binding SomeObject} /> 

Anywhere we use a command, we can pass a parameter. When creating a command, we can use either an Action (a command function without any parameters) or an Action<object> (a command function that takes a single parameter of type 'object'). We can define the command function used above with a lambda expression if preferred:

//  Create the parameterized command.
parameterizedCommand = new Command(
  (parameter) =>
  {
    Messages.Add("Calling a Parameterised Command - the Parameter is '" + 
                 parameter.ToString() + "'.");
  }); 

Example 3: How Does it Work?

Example 4: Disabling or Enabling a Command

Requirement: I need to be able to disable or enable a command - either with code or with XAML.

Every command has the property 'CanExecute'. When this property is set to true, the command is enabled. When this property is false, the command is disabled and the UI is updated accordingly - for example, a button bound to the command will become disabled.

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
      //  Create the enable/disable command, initially disabled.
      enableDisableCommand = new Command(
          () =>
          {
            Messages.Add("Enable/Disable command called.");
          }, false);
    }

    private void DisableCommand()
    {
      //  Disable the command.
      EnableDisableCommand.CanExecute = false;
    }

    private void EnableCommand()
    {
      //  Disable the command.
      EnableDisableCommand.CanExecute = true;
    }
    
    /// <summary>
    /// The command object.
    /// </summary>
    private Command enableDisableCommand;

    /// <summary>
    /// Gets the command.
    /// </summary>
    public Command EnableDisableCommand
    {
      get { return enableDisableCommand; }
    }
}

Now we bind the command to the 'Command' property of a button (or other UI element). We can also bind the 'CanExecute' property of the command.

<CheckBox IsChecked="{Binding EnableDisableCommand.CanExecute, Mode=TwoWay}" Content="Enabled" />
<Button Content="Enable/Disable Command" Command="{Binding EnableDisableCommand}" /> 

We can enable or disable commands in code by setting the CanExecute property. We can also bind to the property to manipulate it from XAML.

Whenever we create a command object (as shown in the constructor), we can pass a boolean as an optional second parameter - this is the initial CanExecute value. By default, it is set to false. In the example above, we set the command to initially disabled.

Example 4: How Does it Work?

Example 5: Commands that Fire Events

Requirement: I need to know when the command has been executed or is about to be executed.

Every Command has two events - Executed, which is called when the Command has been executed, and Executing, which is called when the Command is about to be executed. The Executing event allows the command to be cancelled.

Important note: There is a particular scenario where the events below are very useful. Imagine that you want to pop a message box when the command is about to run to ask the user whether they want to continue - where do you do this? In the command code? That is a bad idea - it forces you to have UI code in you View-Model, which clutters the command but also means that it cannot be run from a unit test. You should do it in the view - and with these events, you can. As another example, what if you wanted to set the focus to a specific control after a command is executed? You cannot do it in the View Model, it doesn't have access to the controls, but by subscribing to the Executed event in the View, we can do this without any problems.

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
      //  Create the events command.
      eventsCommand = new Command(
          () => 
                {
                    Messages.Add("Calling the Events Command.");
                });

Now we bind the command to the 'Command' property of a button (or other UI element).

<Button Content="Events Command" Command="{Binding EventsCommand}" /> 

So far we have nothing different from the first example. However, we will now subscribe to some events in the View. Note: In my View, my DataContext is named 'viewModel'.

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        viewModel.EventsCommand.Executing += 
          new Apex.MVVM.CancelCommandEventHandler(EventsCommand_Executing);
        viewModel.EventsCommand.Executed += 
          new Apex.MVVM.CommandEventHandler(EventsCommand_Executed);
    }

    void EventsCommand_Executed(object sender, Apex.MVVM.CommandEventArgs args)
    {
        viewModel.Messages.Add("The command has finished - this is the View speaking!");
    }

    void EventsCommand_Executing(object sender, Apex.MVVM.CancelCommandEventArgs args)
    {
        if (MessageBox.Show("Cancel the command?", 
                 "Cancel?", 
                 MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            args.Cancel = true;
    }
}

We are starting to get a hint of the power of this Command implementation. We can subscribe to the Executed and Executing events in the View (or even in another ViewModel or another object) and know when they're fired. The Executing event passes a CancelCommandEventArgs object - this has a property called 'Cancel'. If it is set to true, the command will not execute. Both the CommandEventArgs and CancelCommandEventArgs have one more property - Parameter. This is the parameter that has been passed to the Command (if there is one).

Example 5: How Does it Work?

Example 6: An Asynchronous Command

Requirement: My Command function will take a long time - I need it to run asynchronously and not block the UI thread.

Now in this circumstance, we would generally have to do something along the lines of create a background worker and run it in the command function. But we have issues:

  • What if we want to update the ViewModel in the threaded function? We can't, without invoking actions on the UI thread.
  • How do we make sure that the Command isn't pressed twice in short succession, running the thread more than once?
  • How do we keep the View Model clean when we have lots of commands that must be threaded?
  • How do we keep it consistent for WP7 and Silverlight, where we have different options for threading?

The AsynchronousCommand object (which derives from Command) will deal with all of this - and more. Here's how we can use it:

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
      //  Create the async command.
      asyncCommand1 = new AsynchronousCommand(
          () =>
          {
            for (int i = 1; i <= 10; i++)
            {
              //  Report progress.
              asyncCommand1.ReportProgress(() => { Messages.Add(i.ToString()); });

              System.Threading.Thread.Sleep(200);
            }
          });
    }
    
    /// <summary>
    /// The command object.
    /// </summary>
    private AsynchronousCommand asyncCommand1;

    /// <summary>
    /// Gets the command.
    /// </summary>
    public AsynchronousCommand AsyncCommand1
    {
      get { return asyncCommand1; }
    }
}

Now we bind the asynchronous command to the 'Command' property of a button (or other UI element).

<Button Content="Asynchronous Command" Command="{Binding AsyncCommand1}" /> 

As soon as the command is invoked, the function we have provided (via the lambda expression in the constructor) will be called - on a new thread (from the thread-pool).

If we need to do anything with the View Model objects (which may be bound to UI elements), we can do so via the ReportProgress function:

asyncCommand1.ReportProgress(() => { Messages.Add(i.ToString()); });

ReportProgress will ensure that the code that is passed to it will be run on the correct thread (the UI thread). This provides a remarkably easy way for your commands to update the UI as they run.

Example 6: How Does it Work?

Example 7: Changing the UI While an Asynchronous Command is Running

Requirement: My asynchronous command takes a while to run, I'd like to show some progress in the UI.

AsynchronousCommand has a property named 'IsExecuting'. If this is set to true, then the command is running. AsynchronousCommand implements INotifyPropertyChanged, which means that we can bind to this property - and keep our UI fully up to date while the command is running.

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
      //  Create the async command.
      asyncCommand2 = new AsynchronousCommand(
          () =>
          {
            for (char c = 'A'; c <= 'Z'; c++)
            {
              //  Report progress.
              asyncCommand2.ReportProgress(() => { Messages.Add(c.ToString()); });

              System.Threading.Thread.Sleep(100);
            }
          });
    }
    
    /// <summary>
    /// The command object.
    /// </summary>
    private AsynchronousCommand asyncCommand2;

    /// <summary>
    /// Gets the command.
    /// </summary>
    public AsynchronousCommand AsyncCommand2
    {
      get { return asyncCommand2; }
    }
}

Now we bind the asynchronous command to the 'Command' property of a button (or other UI element). We also bind other UI elements to the IsExecuting property of the command.

<Button Content="Asynchronous Command" Command="{Binding AsyncCommand2}" 
        Visibility="{Binding AsyncCommand2.IsExecuting, 
          Converter={StaticResource BooleanToVisibilityConverter}, 
          ConverterParameter=Invert}" />

<StackPanel Visibility="{Binding AsyncCommand2.IsExecuting, 
         Converter={StaticResource BooleanToVisibilityConverter}}">
  <TextBlock Text="The command is running!" />
  <ProgressBar Height="20" Width="120" IsIndeterminate="True" />
</StackPanel>

In this example, as soon as the command starts to run, the button disappears and a text block and progress bar appears. Note that we are binding to the IsExecuting property of the command.

asyncCommand1.ReportProgress(() => { Messages.Add(i.ToString()); });

ReportProgress will ensure that the code that is passed to it will be run on the correct thread (the UI thread). This provides a remarkably easy way for your commands to update the UI as they run.

Note: The 'Invert' parameter can be passed to the BooleanToVisilityConverter because it is an extended version of the standard BooleanToVisibilityConverter that is defined in Apex.Converters. It inverts the result, very useful in these circumstances.

Example 7: How Does it Work?

Example 8: Allowing a User to Cancel an AsynchronousCommand

Requirement: I need to let the user cancel an asynchronous command.

We have a couple of features of AsynchronousCommand that we can use here. Every AsynchronousCommand object contains another Command - named CancelCommand. This can be bound to a UI element (for example, a button named 'Cancel') or invoked via code. When this command is invoked, the 'IsCancellationRequested' property of the AsynchronousCommand is set to true (note that this is a property that uses INotifyPropertyChanged, so you can also bind to it). As long as you periodically call the CancelIfRequested function and return if it returns true, then the cancellation functionality is enabled.

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
       //  Create the cancellable async command.
       cancellableAsyncCommand = new AsynchronousCommand(
         () => 
           {
             for(int i = 1; i <= 100; i++)
             {
               //  Do we need to cancel?
               if(cancellableAsyncCommand.CancelIfRequested())
                 return;

               //  Report progress.
               cancellableAsyncCommand.ReportProgress( () => { Messages.Add(i.ToString()); } );

               System.Threading.Thread.Sleep(100);
             }
           });
    }
    
    /// <summary>
    /// The command object.
    /// </summary>
    private AsynchronousCommand cancellableAsyncCommand;

    /// <summary>
    /// Gets the command.
    /// </summary>
    public AsynchronousCommand CancellableAsyncCommand
    {
      get { return cancellableAsyncCommand; }
    }
}

Now we bind the asynchronous command to the 'Command' property of a button (or other UI element). We also bind other UI elements to the IsExecuting property of the command.

<Button Content="Cancellable Async Command" 
    Command="{Binding CancellableAsyncCommand}" 
    Visibility="{Binding CancellableAsyncCommand.IsExecuting, 
             Converter={StaticResource BooleanToVisibilityConverter},
    ConverterParameter=Invert}" />

<StackPanel Visibility="{Binding CancellableAsyncCommand.IsExecuting, 
      Converter={StaticResource BooleanToVisibilityConverter}}">
  <TextBlock Margin="4" Text="The command is running!" />
  <ProgressBar Margin="4" Height="20" 
     Width="120" IsIndeterminate="True" />
  <Button Margin="4" Content="Cancel" 
      Command="{Binding CancellableAsyncCommand.CancelCommand}" />
</StackPanel>

In this example, we show a button named 'Cancel' when the command is executing. This button binds to the CancellableAsyncCommand.CancelCommand property. Because we use the CancelIfRequested function in our asynchronous function, we can gracefully cancel the asynchronous command.

Note: When an asynchronous command is cancelled - Executed is not called. An event named Cancelled is called instead, which takes the same parameters.

Example 8: How Does it Work?

Example 9: Binding an Event to a Command

Requirement: I have a command that must be invoked, however the UI element which should invoke it does not have a 'Command' property - it only has an event.

In the case of forcing an event to fire a command, we can use an Attached Property named 'EventBindings'. This property and the associated classes are in the Apex.Commands namespace. EventBindings takes an EventBindingCollection, which is a simple collection of EventBinding objects. Each EventBinding object takes the name of the event and the command to fire.

public class MainViewModel : ViewModel
{
    public MainViewModel()
    {
      //  Create the event binding.
      EventBindingCommand = new Command(
        () =>
        {
          Messages.Add("Command called by an event.");
        });
    }
    
    /// <summary>
    /// The command object.
    /// </summary>
    private Command eventBindingCommand;

    /// <summary>
    /// Gets the command.
    /// </summary>
    public Command EventBindingCommand
    {
      get { return eventBindingCommand; }
    }
}

Now we can bind to this command through an event as below:

<Border Margin="20" Background="Red">

  <!-- Bind the EventBindingCommand to the MouseLeftButtonDown event. -->
  <apexCommands:EventBindings.EventBindings>
     <apexCommands:EventBindingCollection>
        <apexCommands:EventBinding EventName="MouseLeftButtonDown" 
            Command="{Binding EventBindingCommand}" />
     </apexCommands:EventBindingCollection>
  </apexCommands:EventBindings.EventBindings>
  
  <TextBlock VerticalAlignment="Center" 
     HorizontalAlignment="Center" Text="Left Click on Me" 
     FontSize="16" Foreground="White" />

</Border> 

By using the EventBindings attached property, we can bind any event to a command.

Example 9: How Does it Work?

How Does it Work?

Every example above has an associated description of how it works under the hood.

The Command Class: Used in Examples 1, 2, 3, 4, and 5

These examples use the 'Command' class, which is described section by section below:

/// <summary>
/// The ViewModelCommand class - an ICommand that can fire a function.
/// </summary>
public class Command : ICommand
{
    /// <summary>
    /// Initializes a new instance of the <see cref="Command"/> class.
    /// </summary>
    /// <param name="action">The action.</param>
    /// <param name="canExecute">if set to <c>true</c> [can execute].</param>
    public Command(Action action, bool canExecute = true)
    {
        //  Set the action.
        this.action = action;
        this.canExecute = canExecute;
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="Command"/> class.
    /// </summary>
    /// <param name="parameterizedAction">The parameterized action.</param>
    /// <param name="canExecute">if set to <c>true</c> [can execute].</param>
    public Command(Action<object> parameterizedAction, bool canExecute = true)
    {
        //  Set the action.
        this.parameterizedAction = parameterizedAction;
        this.canExecute = canExecute;
    }

First of all, we have our two constructors that create the command - passing in an Action or an Action<object>. Action<object> is used for parameterised commands.

Next we have our action (or our parameterized action) as well as the 'canExecute' flag. Note that when the canExecute flag is changed, we must call canExecuteChanged.

/// <summary>
/// The action (or parameterized action) that will be called when the command is invoked.
/// </summary>
protected Action action = null;
protected Action<object> parameterizedAction = null;

/// <summary>
/// Bool indicating whether the command can execute.
/// </summary>
private bool canExecute = false;

/// <summary>
/// Gets or sets a value indicating whether this instance can execute.
/// </summary>
/// <value>
///     <c>true</c> if this instance can execute; otherwise, <c>false</c>.
/// </value>
public bool CanExecute
{
    get { return canExecute; }
    set
    {
        if (canExecute != value)
        {
            canExecute = value;
            EventHandler canExecuteChanged = CanExecuteChanged;
            if (canExecuteChanged != null)
                canExecuteChanged(this, EventArgs.Empty);
        }
    }
}

Following this, we implement the ICommand interface:

/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">Data used by the command.
///  If the command does not require data to be passed,
///  this object can be set to null.</param>
/// <returns>
/// true if this command can be executed; otherwise, false.
/// </returns>
bool ICommand.CanExecute(object parameter)
{
    return canExecute;
}

/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command.
///  If the command does not require data to be passed,
///  this object can be set to null.</param>
void ICommand.Execute(object parameter)
{
    this.DoExecute(parameter);

}

We haven't seen the 'DoExecute' function yet - we'll save that till last.

/// <summary>
/// Occurs when can execute is changed.
/// </summary>
public event EventHandler CanExecuteChanged;

/// <summary>
/// Occurs when the command is about to execute.
/// </summary>
public event CancelCommandEventHandler Executing;

/// <summary>
/// Occurs when the command executed.
/// </summary>
public event CommandEventHandler Executed; 

Remember the examples with the events? Well, here they are - as well as the CanExecuteChanged event required by ICommand.

Before we move onto the DoExecute function, we create an Invoke function for each event, so that we can invoke them in derived classes.

protected void InvokeAction(object param)
{
    Action theAction = action;
    Action<object> theParameterizedAction = parameterizedAction;
     if (theAction != null)
        theAction();
    else if (theParameterizedAction != null)
        theParameterizedAction(param);
}

protected void InvokeExecuted(CommandEventArgs args)
{
    CommandEventHandler executed = Executed;

    //  Call the executed event.
    if (executed != null)
        executed(this, args);
}

protected void InvokeExecuting(CancelCommandEventArgs args)
{
    CancelCommandEventHandler executing = Executing;

    //  Call the executed event.
    if (executing != null)
        executing(this, args);
}

Note that InvokeAction has to be a bit clever - we invoke either the action or the parameterized action, whichever has been set. Finally, we have DoExecute:

/// <summary>
/// Executes the command.
/// </summary>
/// <param name="param">The param.</param>
public virtual void DoExecute(object param)
{
    //  Invoke the executing command, allowing the command to be cancelled.
    CancelCommandEventArgs args = 
       new CancelCommandEventArgs() { Parameter = param, Cancel = false };
    InvokeExecuting(args);

    //  If the event has been cancelled, bail now.
    if (args.Cancel)
        return;

    //  Call the action or the parameterized action, whichever has been set.
    InvokeAction(param);

    //  Call the executed function.
    InvokeExecuted(new CommandEventArgs() { Parameter = param });
}

DoExecute is very straightforward - it calls the appropriate events (cancelling if required!) and that's all there is to it.

This class fully implements ICommand and provides the functionality described in Examples 1, 2, 3, 4, and 5.

The AsynchronousCommand Class: Used in Examples 6, 7, and 8

Examples 6, 7, and 8 use the AsynchronousCommand class, which derives from Command and is described blow-by-blow below.

First we will define the class and the constructors (which call the base):

/// <summary>
/// The AsynchronousCommand is a Command that runs on a thread from the thread pool.
/// </summary>
public class AsynchronousCommand : Command, INotifyPropertyChanged
{
    /// <summary>
    /// Initializes a new instance of the <see cref="AsynchronousCommand"/> class.
    /// </summary>
    /// <param name="action">The action.</param>
    /// <param name="canExecute">if set
    /// to <c>true</c> the command can execute.</param>
    public AsynchronousCommand(Action action, bool canExecute = true) 
      : base(action, canExecute)
    { 
      //  Initialise the command.
      Initialise();
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="AsynchronousCommand"/> class.
    /// </summary>
    /// <param name="parameterizedAction">The parameterized action.</param>
    /// <param name="canExecute">if set to <c>true</c> [can execute].</param>
    public AsynchronousCommand(Action<object> parameterizedAction, bool canExecute = true)
      : base(parameterizedAction, canExecute) 
    {

      //  Initialise the command.
      Initialise(); 
    }

We implement INotifyPropertyChanged so that we can notify when the 'IsExecuting' variable changes. Both constructors call 'Initialise', let's look at this now:

/// <summary>
/// The cancel command.
/// </summary>
private Command cancelCommand;

/// <summary>
/// Gets the cancel command.
/// </summary>
public Command CancelCommand
{
  get { return cancelCommand; }
}

/// <summary>
/// Gets or sets a value indicating whether this instance is cancellation requested.
/// </summary>
/// <value>
///     <c>true</c> if this instance is cancellation requested; otherwise, <c>false</c>.
/// </value>
public bool IsCancellationRequested
{
  get
  {
    return isCancellationRequested;
  }
  set
  {
    if (isCancellationRequested != value)
    {
      isCancellationRequested = value;
      NotifyPropertyChanged("IsCancellationRequested");
    }
  }
}

/// <summary>
/// Initialises this instance.
/// </summary>
private void Initialise()
{
  //  Construct the cancel command.
  cancelCommand = new Command(
    () =>
    {
      //  Set the Is Cancellation Requested flag.
      IsCancellationRequested = true;
    }, true);
}

There's rather a lot here. We've got a Command object (just as in the examples) and all it does is set the 'IsCancellationRequested' flag to true. Initialise creates this object and we have a property to access it. We also have the 'IsCancellationRequested' property, which notifies when it is changed. As we will also want to know when we're executing, let's add a property for that:

/// <summary>
/// Flag indicating that the command is executing.
/// </summary>
private bool isExecuting = false;

/// <summary>
/// Gets or sets a value indicating whether this instance is executing.
/// </summary>
/// <value>
///     <c>true</c> if this instance is executing; otherwise, <c>false</c>.
/// </value>
public bool IsExecuting
{
  get
  {
    return isExecuting;
  }
  set
  {
    if (isExecuting != value)
    {
      isExecuting = value;
      NotifyPropertyChanged("IsExecuting");
    }
  }
}

Not too bad. As we allow cancellation, we'll need a Cancelled event and the PropertyChanged event (from INotifyPropertyChanged):

/// <summary>
/// The property changed event.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// Occurs when the command is cancelled.
/// </summary>
public event CommandEventHandler Cancelled; 

Aside from the standard wiring up of NotifyPropertyChanged and the cancellation flag, the real interest is in DoExecute:

/// <summary>
/// Executes the command.
/// </summary>
/// <param name="param">The param.</param>
public override void DoExecute(object param)
{
  //  If we are already executing, do not continue.
  if (IsExecuting)
    return;

  //  Invoke the executing command, allowing the command to be cancelled.
  CancelCommandEventArgs args = 
     new CancelCommandEventArgs() { Parameter = param, Cancel = false };
  InvokeExecuting(args);

  //  If the event has been cancelled, bail now.
  if (args.Cancel)
    return;

  //  We are executing.
  IsExecuting = true;

We never run the command if it is already executing. Following this, we allow the command to be cancelled and set the executing flag:

//  Store the calling dispatcher.
#if !SILVERLIGHT
      callingDispatcher = Dispatcher.CurrentDispatcher;
#else
      callingDispatcher = System.Windows.Application.Current.RootVisual.Dispatcher;
#endif

We must store the dispatcher that the command is executed on. Why? So that when we report progress, we report it on the appropriate dispatcher. We have to be careful how we store the calling dispatcher, as it works a little different between Silverlight and WPF.

// Run the action on a new thread from the thread pool
// (this will therefore work in SL and WP7 as well).
ThreadPool.QueueUserWorkItem(
    (state) =>
    {
      //  Invoke the action.
      InvokeAction(param);

      //  Fire the executed event and set the executing state.
      ReportProgress(
        () =>
        {
          //  We are no longer executing.
          IsExecuting = false;

          //  If we were cancelled,
          //  invoke the cancelled event - otherwise invoke executed.
          if(IsCancellationRequested)
            InvokeCancelled(new CommandEventArgs() { Parameter = param });
          else
            InvokeExecuted(new CommandEventArgs() { Parameter = param });

          //  We are no longer requesting cancellation.
          IsCancellationRequested = false;
        }
      );
    }
  );
}

Now the clever stuff. Using the thread pool, we queue the InvokeAction function - this will call the command function (on a new thread). Now remember - ReportProgress runs on the calling dispatcher, so that's where we must change properties and call Executed etc. So on the calling dispatcher (once the action is finished), we clear the 'IsExecuting' flag and invoke either Cancelled or Executed depending on whether the event was cancelled. That's it. We're only left with ReportProgress:

/// <summary>
/// Reports progress on the thread which invoked the command.
/// </summary>
/// <param name="action">The action.</param>
public void ReportProgress(Action action)
{
  if (IsExecuting)
  {
    if (callingDispatcher.CheckAccess())
      action();
    else
      callingDispatcher.BeginInvoke(((Action)(() => { action(); })));
  }
} 

With ReportProgress, we invoke the provided action on the calling dispatcher, or just invoke it if we are the calling dispatcher.

A Note on Unit Testing and the AsynchronousCommand

If you are having any difficulty unit testing AsynchronousCommand objects, it is because when unit testing, there is no Dispatcher Frame. There is an explanation on dealing with this here: consistentmvvmcommands.aspx?msg=4084944#xx4084944xx.

The EventBindings: Used in Example 9

The EventBindings code has a few more complexities due to the differences between WPF and Silverlight. In WPF, EventBindingsCollection is a FreezableCollection. This is so that the children of the collection (the event bindings) inherit the data context of the parent element. In Silverlight, we do not have a FreezableCollection, so we must set the datacontext of each event binding ourselves. Here's how the EventBindings property is defined:

public static class EventBindings
{
  /// <summary>
  /// The Event Bindings Property.
  /// </summary>
    private static readonly DependencyProperty EventBindingsProperty =
      DependencyProperty.RegisterAttached("EventBindings", 
      typeof(EventBindingCollection), typeof(EventBindings),
      new PropertyMetadata(null, new PropertyChangedCallback(OnEventBindingsChanged)));

    /// <summary>
    /// Gets the event bindings.
    /// </summary>
    /// <param name="o">The o.</param>
    /// <returns></returns>
    public static EventBindingCollection GetEventBindings(DependencyObject o)
    {
        return (EventBindingCollection)o.GetValue(EventBindingsProperty);
    }

    /// <summary>
    /// Sets the event bindings.
    /// </summary>
    /// <param name="o">The o.</param>
    /// <param name="value">The value.</param>
    public static void SetEventBindings(DependencyObject o, 
                       EventBindingCollection value)
    {
        o.SetValue(EventBindingsProperty, value);
    }

    /// <summary>
    /// Called when event bindings changed.
    /// </summary>
    /// <param name="o">The o.</param>
    /// <param name="args">The <see
    /// cref="System.Windows.DependencyPropertyChangedEventArgs"/>
    /// instance containing the event data.</param>
    public static void OnEventBindingsChanged(DependencyObject o, 
           DependencyPropertyChangedEventArgs args)
    {
        //  Cast the data.
        EventBindingCollection oldEventBindings = 
          args.OldValue as EventBindingCollection;
        EventBindingCollection newEventBindings = 
          args.NewValue as EventBindingCollection;

        //  If we have new set of event bindings, bind each one.
        if (newEventBindings != null)
        {
            foreach (EventBinding binding in newEventBindings)
            {
                binding.Bind(o);
#if SILVERLIGHT
                //  If we're in Silverlight we don't inherit the
                //  data context so we must set this helper variable.
                binding.ParentElement = o as FrameworkElement;
#endif
            }
        }
    }
}

As we can see, the only function of real interest is EventBinding.Bind, which is listed below:

public void Bind(object o)
{
    try
    {
        //  Get the event info from the event name.
        EventInfo eventInfo = o.GetType().GetEvent(EventName);

        //  Get the method info for the event proxy.
        MethodInfo methodInfo = GetType().GetMethod("EventProxy", 
                   BindingFlags.NonPublic | BindingFlags.Instance);

        //  Create a delegate for the event to the event proxy.
        Delegate del = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo);

        //  Add the event handler. (Removing it first if it already exists!)
        eventInfo.RemoveEventHandler(o, del);
        eventInfo.AddEventHandler(o, del);
    }
    catch (Exception e)
    {
        string s = e.ToString();
    }
}

This is a standard approach to this requirement, I have seen it in other articles. However, we must be a bit more careful in our event proxy (this I haven't seen before):

/// <summary>
/// Proxy to actually fire the event.
/// </summary>
/// <param name="o">The object.</param>
/// <param name="e">The <see
///    cref="System.EventArgs"/> instance
///    containing the event data.</param>
private void EventProxy(object o, EventArgs e)
{   
#if SILVERLIGHT

    //  If we're in Silverlight, we have NOT inherited the data context
    //  because the EventBindingCollection is not a framework element and
    //  therefore out of the logical tree. However, we can set it here 
    //  and update the bindings - and it will all work.
    DataContext = ParentElement != null ? ParentElement.DataContext : null;
    var bindingExpression = GetBindingExpression(EventBinding.CommandProperty);
    if(bindingExpression != null)
        bindingExpression.UpdateSource();
    bindingExpression = GetBindingExpression(EventBinding.CommandParameterProperty);
    if (bindingExpression != null)
        bindingExpression.UpdateSource();

#endif

    if (Command != null)
        Command.Execute(CommandParameter);
}

Final Thoughts

In the example applications I have provided, the ViewModel class is the same in every project - this code works exactly the same in WPF, Silverlight, and WP7.

I hope you find this article useful, please let me know via the Comments section if you notice any problems.

To keep up to date on Apex development, you can see my blog: www.dwmkerr.com or the Apex CodePlex page: apex.codeplex.com.


深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值