系列目錄:
MVVM模式解析和在WPF中的實現(五)View和ViewModel的通訊
MVVM模式解析和在WPF中的實現(六)用依賴注入的方式配置ViewModel並註冊訊息
0x00 為什麼要事件繫結
這個問題其實是很好理解的,因為事件是豐富多樣的,單純的命令繫結遠不能覆蓋所有的事件。例如Button的命令繫結能夠解決Click事件的需求,但Button的MouseEnter、窗體的Loaded等大量的事件要怎麼處理呢?這就用到了事件繫結。
0x01 事件繫結
要使用事件繫結需要藉助System.Windows. interactivity,如果安裝了Blend,裡面就包含了這個dll。需要在Interaction.Triggers裡面新增一個或多個EventTrigger並指定關注的的事件名稱,在EventTrigger中通過InvokeCommandAction來繫結事件對應的命令。圖中所示繫結了主視窗的Loaded事件,在事件觸發後會呼叫繫結的命令物件LoadedCommand的Execute方法執行命令,當命令繫結需要引數時可以通過繫結CommandParameter實現。需要指出的是之前在實現MyCommand的Execute方法時我們加入了CanExecute的判斷,因此事件觸發後是否能夠真正執行繫結的命令也受到繫結的LoadedCommand的CanExecute方法的影響。
0x02 帶EventArgs引數的事件繫結
上面介紹的事件繫結並不足以應對所有的情況,因為很多情況下我們還需要從事件的EventArgs中獲取資料,例如從MouseMove事件引數中獲取滑鼠位置和按鍵狀態等。但InvokeCommandAction在未對CommandParameter繫結的情況下給Execute方法傳遞的引數為null。因此我們需要自己寫一個類來處理事件到命令的繫結。
看一下上面我們用到的InvokeCommandAction,繼承自TriggerAction<DependencyObject>,TriggerAction是一個抽象類,我們只要繼承這個類並實現Invoke方法即可。TriggerAction在MSDN中的介紹如下:
我簡單實現了以下,程式碼如下圖所示,其中依賴項屬性是藉助propdp程式碼段生成的,要不實在記不住,輸入那麼多程式碼也好麻煩。使用的時候用來代替之前的InvokeCommandAction,不繫結CommandParameter則傳遞的就是事件的引數。如果繫結了CommandParameter,那麼傳遞的就是繫結的引數。
0x03 事件繫結的示例
有了MyEventCommand我們就可以繫結事件並獲取事件引數了。例項中繫結了窗體的Loaded事件和MouseMove事件,其中在MouseMove事件中我們使用自己的MyEventCommand物件接收事件物件,並顯示出滑鼠相對於窗體的位置以及各個按鍵的狀態。
示例程式執行後如下所示
0x04 相關下載
https://github.com/durow/TestArea/tree/master/MVVMTest/EventBindingTest