我们从一个情景开始:为前台一个 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
。
Comments NOTHING