Alex Rivera | Logout

Is it okay to use ICommand in view-model

Asked 2013-03-12T19:15:17.490
12

Most of the WPF mvvm applications, we are using ICommand in the view-model. But it is referring to System.Windows.Input. so the view-model is now tightly couple with System.Windows.Input namespace. according to my understanding view-model should be able to use in normal C# winform application or asp.net application.

Normally we are using following code lines to the command with RelayCommand implementation.

private RelayCommand testCommand;// or private ICommand testCommand;

public ICommand TestCommand
{
    get
    {
        return testCommand ?? 
            (testCommand = new RelayCommand(param => Test()));
    }
}

public void Test()
{

}

What i feel is we need to remove all the ICommand and use RelayCommand instead. So we can eliminate the System.Windows namespace from the view-model. so final code will looks like this,

private RelayCommand testCommand;

public RelayCommand TestCommand
{
    get
    {
        return testCommand ?? 
            (testCommand = new RelayCommand(param => Test()));
    }
}

public void Test()
{

}

Any suggestions on this approach? or is there any way to eliminate the System.Windows namespace from the view-model?

Edit
Report

1 Answer

6

Pretty simple to avoid coupling your ViewModel to ICommand, if you want to. Probably not a bad idea, WPF will probably go the way of MFC one day. Overkill? maybe, but here is a how:

In your view:

<StackPanel>
    <Button Command="{Binding Path=MyCommand}"> Do it! Kill me Now!</Button>
    <TextBlock Text="{Binding Path=Message}"></TextBlock>
</StackPanel>

Inject your ViewModel into your DataContext, Take the responsibility for the native commands, out of your view model:

public class ViewModel : INotifyPropertyChanged
{
    public string Message { get; set; }
    public object MyCommand { get; set; }


    public void OnMyCommand(object parameter)
    {
        Message += "I Ran something" + Environment.NewLine;
    }

    public bool CanMyCommand(object parameter)
    {
        return true;
    }

    // Injected Native Command handler
    public ViewModel(ICommandFactory factory)
    {
        MyCommand = factory.CreateInstance(OnMyCommand, CanMyCommand);
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Note I'm using FODY to weave in the property change handler. INotifyPropertyChanged is System.dll btw.

Now, Bind this contract:

public interface ICommandFactory
{
    object CreateInstance(Action<object> action, Func<object, bool> predicate);
}

... to something that will give you a native Command object;

public class NativeCommand : ICommand
{
    private readonly Action<object> _action;
    private readonly Func<object, bool> _predicate;

    public NativeCommand(Action<object> action, Func<object, bool> predicate)
    {
        _action = action;
        _predicate = predicate;
    }

 
answered 2013-03-12T20:46:20.663

Your Answer