如何在MVVM Light框架中使用RelayCommand

24

我刚开始学习MVVM Light框架,但找不到任何如何使用RelayCommand的简单示例。为了学习,我想在我的视图中有一个按钮,当点击它时,会显示一个“Hello World”消息框,且每隔偶数分钟(即DateTime.Now.Minute % 2 == 0)该按钮可用。

这个按钮的XAML应该是什么样子的,以及如何在ViewModel中定义HelloWorld RelayCommand?

谢谢你的帮助!

2个回答

48

RelayCommand的目的是实现ICommand接口,以满足Button控件的需要,并将调用传递到位于ViewModel旁边的其他函数。

例如,您可能会有一个ViewModel类如下:

class HelloWorldViewModel : ViewModelBase
{
    public RelayCommand DisplayMessageCommand { get; private set; }

    private DispatchTimer _timer;

    public HelloWorldViewModel()
    {
        this.DisplayMessageCommand = new RelayCommand(this.DisplayMessage, CanDisplayMessage);

        // Create a timer to go off once a minute to call RaiseCanExecuteChanged
        _timer = new DispatchTimer();
        _timer = dispatcherTimer.Tick += OnTimerTick;
        _timer.Interval = new Timespan(0, 1, 0);
        _timer.Start();
    }

    private void OnTimerTick(object sender, EventArgs e)
    {
        this.DisplayMessageCommand.RaiseCanExecuteChanged();
    }

    public bool CanDisplayMessage()
    {
        return DateTime.Now.Minute % 2 == 0;
    }

    public void DisplayMessage()
    {
        //TODO: Do code here to display your message to the user
    }
}

在你的控件中,你可以通过在代码中或直接在XAML中使用DataContext={StaticResource ...}来设置DataContext

然后,你可以通过以下方式将按钮绑定到ViewModel中的命令:

<Button Content='Push me' Command='{Binding DisplayMessageCommand}' />
当单击按钮时,它使用DisplayMessageCommand并在此对象上调用Execute(),而RelayCommand则将其转发到DisplayMessage方法。 DispatchTimer每分钟触发一次,并调用RaiseCanExecuteChanged()。这允许绑定到该命令的按钮重新检查命令是否仍然有效。否则,您可能会发现单击按钮时命令当前不可用。

只是出于好奇,是否有一种方法将命令的CanDisplayMessage()绑定到IsEnabled属性? - Evan
@evan,如果你指的是Button的IsEnabled属性?如果你在Button上设置了Command对象,这将自动完成。 - MerickOWA
5
除了这个非常完整的例子之外,请注意以下内容:
  • 如果您不想为 Execute 和 CanExecute 方法命名,可以使用 Lambda 表达式作为委托。
  • 除了所有 ButtonBase 控件(Button、RadioButton、CheckBox 等)上的 Command 属性之外,您还可以使用 EventToCommand 行为(在 MVVM Light "extras" 中可用)将任何事件绑定到命令。
- LBugnion
@LBurgnion - 感谢您指出EventToCommand,这很好知道! - Evan
让我为您修复一下... public ICommand DisplayMessageCommand { get; private set; } - hyankov

5
或者使用lambda。
    private RelayCommand<anyobject> _AddCmd;
    public ICommand AddPoint
    {
        get
        {
            return _AddCmd ??
                (
                _AddCmd = new RelayCommand
                    (
                        (obj) =>
                        {
                            ViewModelWF.ZeroPoints.Add(new WM.Point(0, 0));
                        }
                    )
                );
        }
    }

    private RelayCommand _DeleteCmd;
    public ICommand DeletePoint
    {
        get
        {
            return _DeleteCmd ??
                (
                _DeleteCmd = new RelayCommand
                    (
                        () =>
                        {
                            int idx = wpfZeroPoints.SelectedIndex;
                        },
                        () =>
                        {
                            return wpfZeroPoints.SelectedIndex <= 0;
                        }
                    )
                );
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接