透過 DelegateCommand 綁定方法
先前文章綁定的方法都是透過綁定具 Command 屬性的來源,包括 MenuItem, Button 與 KeyGesture
如果想綁定不是 Command 的事件,顯然就不能用 RelayCommand 的辦法!比如 Page 的 PeLoad 或 Form 的 Load
這裡用另一個辦法來解決,使用 System.Windows.Interactivity 來 Trigger 事件,Interactivity 是 Expression Blend 的附屬功能
首先要安裝這套件,我選擇用 NuGet 來安裝
也可使用 Visual Studio Installer 安裝這個附加功能,或是有保留參考 DLL 也可以用加入參考啟用功能
先把基本的 DelegateCommand 建立起來
using System;
using System.Diagnostics;
using System.Windows.Input;
namespace MVVM
{
public class DelegateCommand : ICommand
{
private readonly Func<object, bool> _canExecute;
private readonly Action<object> _execute;
bool canExecuteCache;
// 建構子(多型)
public DelegateCommand(Action<object> execute, object canExecute) : this(execute, null)
{
}
// 建構子(傳入參數)
public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
{
// 簡化寫法 if(execute == null) throw new ArgumentNullException("execute");
this._execute = execute ?? throw new ArgumentNullException("execute");
this._canExecute = canExecute;
}
#region -- ICommand Members --
// 在XAML使用Interaction繫結這個事件
public event EventHandler CanExecuteChanged;
// 下面兩個方法是提供給 View 使用的
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
bool temp = _canExecute(parameter);
if (canExecuteCache != temp)
{
canExecuteCache = temp;
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, new EventArgs());
}
}
return canExecuteCache;
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
}
}
這次範例也是用 Button 來示範,在 ViewModel 裡加上以下程式碼,建構式內要初始化對應的 DelegateCommand 類別方法
public class TestViewModels : ViewModelBase // ViewModelBase繼承INotifyPropertyChanged介面
{
public TestViewModels()
{
//初始化DelegateCommand
cm1click = new DelegateCommand(cm1Click, CanExecute);
}
private bool CanExecute(object param)
{
return true; // 假設都執行
}
// DelegateCommand
#region command1
public ICommand cm1click { get; set; }
private void cm1Click(object param)
{
MessageBox.Show("CM1 clicked!");
}
#endregion command1
}
對應的 View 的 xaml 部分加入命名空間 - interactivity
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
或是以下方式也是一樣引入 interactivity 的命名空間
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
使用 Interactivity 主要是透過 <i:Interaction.Trigger> 標記想觸發的事件到事件觸發器 <i:EventTrigger> 內,並透過 <i:InvokeCommandAction> 綁定想執行的命令/方法
xaml 再加入以下部分
<Button x:Name="BTN_CM1" Content="DelegateCommand">
<i:Interaction.Triggers>
<i:EventTrigger EventName = "Click">
<i:InvokeCommandAction Command = "{Binding cm1click}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
對照之前的 RelayCommand 的範例來看,DelegateCommand 的 xaml 部分更直覺了!
想修改綁定給其事件,也只要變更 EventName 就完成綁定修改!
而且所有事件都可以綁定,這是更大的優勢部分!
但簡單應用 RelayCommand 還是很方便使用的,就看用途來決定用哪種方法囉~