Click here to Skip to main content
15,890,825 members
Articles / Desktop Programming / WPF

Asynchronous WPF Command

Rate me:
Please Sign up or sign in to vote.
1.00/5 (1 vote)
27 Jan 2012CPOL 17K   3  
Asynchronous WPF command

The ICommand interface provides a nice way of binding WPF buttons to methods in a view model. If those methods use any amount of time, though, you'll want to run them in a background thread.

This implementation of ICommand is an easily-extendable way to run methods in an async manner when a button is clicked. The base class creates a BackgroundWorker that runs a proxy for the Execute method. All you have to do is override OnExecute.

The...

C#
BeforeExecute

...method allows you to run operations on the UI thread immediately before the BackgroundWorker does its async operation.

The...

C#
AfterExecute

...method allows you to run operations after the BackgroundWorker completes its work. It also provides the Exception object (if one was thrown) that was thrown in the background thread.

/// <summary>
/// Implementation of <c>ICommand</c> that allows for asynchronous operation.
/// </summary>
public class AsyncCommandBase : ICommand
{
    /// <summary>
    /// Raises the <c>CanExecuteChanged</c> event for the command.
    /// </summary>
    /// <remarks>This method should be invoked whenever the 
    /// returned value of <c>CanExecute</c> changes.</remarks>
    protected void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null) CanExecuteChanged(this, new EventArgs());
    }
 
    /// <summary>
    /// When overridden in a derived class, performs operations in the UI thread
    /// before beginning the background operation.
    /// </summary>
    /// <param name="parameter">The parameter passed to the 
    /// <c>Execute</c> method of the command.</param>
    protected virtual void BeforeExecute(object parameter) { }
 
    /// <summary>
    /// When overridden in a derived class, performs operations in a background
    /// thread when the <c>Execute</c> method is invoked.
    /// </summary>
    /// <param name="parameter">The parameter passed to the 
    /// <c>Execute</c> method of the command.</param>
    protected virtual void OnExecute(object parameter) { }
 
    /// <summary>
    /// When overridden in a derived class, performs operations when the
    /// background execution has completed.
    /// </summary>
    /// <param name="parameter">The parameter passed to the 
    /// <c>Execute</c> method of the command.</param>
    /// <param name="error">The error object that was thrown 
    /// during the background operation, or null if no error was thrown.</param>
    protected virtual void AfterExecute(object parameter, Exception error) { }
 
    /// <summary>
    /// Occurs when changes occur that affect whether or not the command should execute.
    /// </summary>
    public event EventHandler CanExecuteChanged;
 
 
    /// <summary>
    /// When overridden in a derived class, 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>
    public virtual bool CanExecute(object parameter)
    {
        return true;
    }
 
    /// <summary>
    /// Runs the command method in a background thread.
    /// </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>
    public void Execute(object parameter)
    {
        BeforeExecute(parameter);
 
        var bgw = new BackgroundWorker();
 
        bgw.DoWork += (s, e) =>
        {
            OnExecute(parameter);
        };
        bgw.RunWorkerCompleted += (s, e) =>
        {
            AfterExecute(parameter, e.Error);
        };
        bgw.RunWorkerAsync();
    }
}
This article was originally posted at http://kendoll.net/async_wpf_command

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --