djskinner
djskinner

Reputation: 8125

MVVM Multiple Command Handlers

My Application layer uses DialogPresenters to show some ViewModels in various dialogs (modal, splash screen, etc..).

    public DataImportDialogPresenter(DataImportViewModel viewModel, IDialogView shellView, IDialogView owner)
        : base(viewModel, shellView, owner)
    {
        //Base sets the view data context etc.
        //Monitor CancelCommand and close the dialog
        viewModel.CancelCommand = new DelegateCommand(() => Terminate());
    }

This setup works really well except for the fact that if my ViewModel decides it needs to do something on the CancelCommand (which is perfectly reasonable) then it will replace the presenter's call to Terminate() or vice-versa.

What I would like to do is:

viewModel.CancelCommand += new DelegateCommand(() => Terminate());

In the same spirit as attaching event handlers.

  1. Is this possible in C#.NET 3.5?
  2. How would I achieve it?
  3. Is this bad MVVM practice?

Thanks

D

Upvotes: 2

Views: 1292

Answers (1)

Thomas Levesque
Thomas Levesque

Reputation: 292685

You could use another implementation of the ICommand interface, that would wrap the original CancelCommand of the ViewModel :

public class WrapperDelegateCommand : ICommand
{
    private Action<object> _action;
    private ICommand _originalCommand;

    public WrapperDelegateCommand(Action<object> action, ICommand original)
    {
        _action = action;
        _originalCommand = original;
    }

    public bool CanExecute(object param)
    {
        if (originalCommand != null)
            return _originalCommand.CanExecute(param);
        return true;
    }

    public void Execute(object param)
    {
        if (_originalCommand != null)
            _originalCommand.Execute(param);
        _action(param);
    }

    public ICommand OriginalCommand { get { return _originalCommand; } }
}

You can then assign this command to the ViewModel's command :

viewModel.CancelCommand = new WrapperDelegateCommand(() => Terminate(), viewModel.CancelCommand);

And you should probably restore the original command in the Terminate method :

viewModel.CancelCommand = (viewModel.CancelCommand as WrapperDelegateCommand).OriginalCommand;

Upvotes: 2

Related Questions