Passing parameters to MVVM Command

时间:2016-02-12 19:30:04

标签: c# wpf mvvm

Does anyone knows how to pass parameters to Command using CommandHandler? Let's assume I would like to pass string hard coded value from XAML. I know how to pass from XAML, but not how to handle it in MVVM code behind. The code below works fine if there is no need to pass any parameters.

public ICommand AttachmentChecked
{
    get
    {
        return _attachmentChecked ?? (_attachmentChecked = new CommandHandler(() => ExecuteAttachmentChecked(), CanExecuteAttachmentChecked()));
    }
}

private void ExecuteAttachmentChecked()
{        
}

private bool CanExecuteAttachmentChecked()
{
    return true;
}

CommandHandler:

public class CommandHandler : ICommand
{
    private Action _action;
    private bool _canExecute;

    public CommandHandler(Action action, bool canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action();
    }
}

4 个答案:

答案 0 :(得分:10)

You need to change two things

1.Change your Commandhandler to accept parameter

 public class CommandHandler : ICommand
{
    private Action<object> _action;
    private bool _canExecute;
    public CommandHandler(Action<object> action, bool canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action(parameter);
    }
}

2.Change the method to accept the CommandParameter:

public ICommand AttachmentChecked
{
    get
    {
        return _attachmentChecked ?? (_attachmentChecked = new CommandHandler(param => ExecuteAttachmentChecked(param), CanExecuteAttachmentChecked()));
    }
}

private void ExecuteAttachmentChecked(object param)
{
 //param will the value of `CommandParameter` sent from Binding
}

private bool CanExecuteAttachmentChecked()
{
    return true;
}

答案 1 :(得分:9)

You should just write your string into CommandParameter:

<Button Command="{Binding NextCommand}" 
CommandParameter="Hello" 
Content="Next" />

and change from:

private Action _action;
private bool _canExecute;

to allow accept parameters:

readonly Action<object> _execute;        
readonly Predicate<object> _canExecute;

Assuming that you are using RelayCommand in parameter obj of method DoSmth will be "Hello":

public RelayCommand YourCommand { get; set; }
public YourViewModel()
{
    NextCommand = new RelayCommand(DoSmth);
}

private void DoSmth(object obj)
{
    Message.Box(obj.ToString()); 
}

答案 2 :(得分:7)

这已经得到了解答,但您可能不知道有一些框架可以避免与MVVM中的命令(和INotifyPropertyChanged)相关的样板代码。

其中最着名的是MVVM Light,它会为你处理一些事情。

使用此框架,您可以使用参数处理命令:

(注意:我们将创建一个更改UserControl显示的命令,因为UserControl是应用程序的“主要部分”)

1)在ViewModel中,定义一个带参数类型的RelayCommand(在本例中为UserControl)

public RelayCommand<UserControl> changePageCommand { get; private set; }

2)定义要绑定到命令的方法(在此简化)

public void navigate(UserControl nextPage)
{
    currentUserControl = nextPage; 
}

3)将命令绑定到刚刚定义的方法

changePageCommand = new RelayCommand<UserControl>((page) => navigate(page));

您的命令现已全部设置好并可以在XAML中使用,假设您要切换带有菜单选项的页面,例如......

4)使用参数绑定命令到控件(XAML)

<Menu>
    <MenuItem Header="_Pages">
        <MenuItem Header="_Account"
                  Command="{Binding changePageCommand}"
                  CommandParameter="{Binding pageManager.accountPage}" />
        <MenuItem Header="_Profile"
                  Command="{Binding changePageCommand}"
                  CommandParameter="{Binding pageManager.profilePage}" />
    </MenuItem>
</Menu>

注意:pageManager只是一个将我的所有页面初始化为默认状态的类,显然在我的ViewModel中引用了它。

希望这可以帮助您或任何路过的人

答案 3 :(得分:5)

The parameter is passed in the ICommand.Execute method, you just need to pass it through to your handler.

public class CommandHandler : ICommand
{
    private Action<object> _action;
    private bool _canExecute;
    public CommandHandler(Action<object> action, bool canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _action(parameter);
    }
}