我们从一个情景开始:为前台一个 Button 绑定触发 Click 事件后的处理动作。

非 MVVM 模式

先来看看 WPF 中默认的前台事件绑定后台动作的方法。

MainWindow.xaml:

<Button Click="Button_Click">
    开始转换
</Button>

MainWindow.cs:

private void Button_Click(object sender, RoutedEventArgs e)
{
    // do sth
}

MVVM 模式

如果要转为 MVVM,那就不能用 Click,因为这不会绑定到自己写的 ViewModel 上。

这里使用 Prism.Core nuget 包,因为这个是跨平台的。参见:https://prismlibrary.com/docs/commands/commanding.html

MainWindow.xaml:

<Button Command="{Binding SubViewModel.SaveAndConnectCommand}">
    开始转换
</Button>

MainWindow.cs:

// 构造函数
public MainWindow()
{
    InitializeComponent();
    // 绑定 ViewModel 
    var coreVM = new CoreViewModel();
    DataContext = coreVM;
}

CoreViewModel.cs

public DelegateCommand TestCommand { get; private set; }
public CoreViewModel()
{
    TestCommand = new DelegateCommand(Test);
}
private void Test()
{
    // do sth
}

传递参数

如果打算传自定义参数,可以在 XAML 中使用 CommandParameter 参数。但是如果要传原本非 MVVM 模式中的 EventArgs 呢?

最笨的方法是:按照非 MVVM 的方法在后台 .cs 文件写一个处理方法,然后这个方法又去调用 ViewModel 里的真正的处理方法。

微软官方仓库的 issue (https://github.com/Microsoft/XamlBehaviors/issues/126)中提到可以原生支持传递 Sender 和 EventArgs,但是我尚不清楚在 ViewModel 里要怎么写。

此外,Prism 可以使用 TriggerParameterPath 参数传递 EventArgs 里的某个属性。但是如何传递整个 EventArgs 以及 Sender 尚不清楚。 参见:https://prismlibrary.com/docs/wpf/interactivity/event-to-command.html

最后就是我目前在用的方法。https://stackoverflow.com/questions/40104765/bind-event-in-mvvm-and-pass-event-arguments-as-command-parameter

首先在前台 XAML 的命名空间中引入:(https://stackoverflow.com/questions/20743961/the-name-interaction-does-not-exist-in-the-namespace-http-schemas-microsoft

xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

然后 button 的触发事件写:

<Button>
    开始转换
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <i:CallMethodAction TargetObject="{Binding}"
                                MethodName="TestClick"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

CoreViewModel.cs

public void TestClick(object sender, RoutedEventArgs e)
{
    // do sth
}

VM 中的方法要是 public


封面图:https://www.pixiv.net/artworks/90486349