Prism 源碼解讀5-數據綁定和命令
- 2020 年 4 月 4 日
- 筆記
介紹
WPF本身就支援通知、綁定和命令,實現ViewModel和VIew之間的通訊,但相對來說功能比較少,Prism擴充了這些功能並提供更加強有力,簡潔的數據綁定和命令。
0 綁定通知
WPF的綁定通知需要實現INotifyPropertyChanged介面,也就是實現一個屬性改變事件,用來通知UI屬性改變了,讓UI更新。該事件需要一個事件參數new PropertyChangedEventArgs(propertyName)傳入屬性的名字,這樣的調用方式比較繁瑣。
Prism擴充了WPF的綁定通知。提供了BindableBase 實現了 INotifyPropertyChanged介面,並使用CallerMemberName獲取屬性名字。這樣就解決了屬性改變事件調用繁瑣的問題。同時在內部還是對相等值進行了過濾。
簡單愉快的調用吧
只需要使用SetProperty方法就可以自動更新UI了。
值得注意的是OnPropertyChanged還提供了對Expression的支援
也就是主動調用OnPropertyChanged(()=>this.PropertyName),也可以觸發UI響應。
1 命令
DelegateCommand
WPF命令和通知有點類似,命令需要實現ICommand介面,實現Execute方法,命令狀態CanExecute和命令狀態改變事件。並且WPF只實現了一個RoutedCommand。Prism提供了一個DelegateCommandBase命令基類實現ICommand,並擴充了子類DelegateCommand,大大簡化了命令調用方式
看到在基類中有_synchronizationContext執行緒同步上下文,用來保證命令執行的時候執行緒同步。
重點關注一下子類中的幾個方法
1.ExecuteDelegateCommand = new DelegateCommand(Execute, CanExecute);
- 這個命令聲明方式,如果命令狀態發生變化的時候需要主動調用RaiseCanExecuteChanged方法來觸發命令狀態改變事件。
2.DelegateCommandObservesProperty = new DelegateCommand(Execute, CanExecute).ObservesProperty(() => IsEnabled);
- 可以看到這種聲明方式,提供了一個ObservesProperty方法,不需要顯示調用命令狀態改變事件。
3.DelegateCommandObservesCanExecute = new DelegateCommand(Execute).ObservesCanExecute(() => IsEnabled);
- 這種聲明方法提供ObservesCanExecute方法,直接觀測命令狀態改變事件和屬性。
4.ExecuteGenericDelegateCommand = new DelegateCommand
- 這是一個使用泛型帶參數的聲明方式,
看一下內部怎麼實現這種簡單而強大的功能
通過Expression,內部調用PropertyObserver.Observes()方法並將RaiseCanExecuteChaned方法傳入。
在PropertyObserver將Expression保存在一個鏈表,並每個節點都訂閱OnPropertyChanged事件。
CompositeCommand
Prism還提供了一個CompositeCommand命令
這個命令的功能跟其名字一樣,就是複合命令,命令集合。
- 將DelegateCommand實例放到其中,每當調用CompositeCommand調用的時候會調用它保存的所有命令,
- 命令集合中任何一個命令狀態改變,都會觸發CompositeCommand命令狀態的改變事件,導致CompositeCommand檢查集合中所有的命令狀態,首先會檢查IActiveAware,再檢查命令狀態,如果任何一個命令狀態是False,都會導致組合命令返回False
來看一下源碼
注意到,聚合命令也是通過執行緒上下文保持執行緒同步,同時看到有檢測IActiveAware介面,這個介面是什麼意思呢?其實就是查看該命令是否激活。這個介面有一個激活狀態屬性和一個激活狀態改變事件,
只要介面主動調用UpdateCommand.IsActive = true;命令就會被激活並觸發複合命令的激活狀態改變回調函數
在複合命令的ShouldExcute方法中檢查其激活狀態,命令集合中沒有激活命令,那麼複合命令的執行狀態也會改變。
命令執行和激活狀態都是差不多的介面,有狀態和狀態改變事件組成,感覺很多地方都有相似的模式,有點像訂閱模式,也有點像狀態機,包括一些Collection和Storage.
總結
主要講了下Prism提供的綁定通知和命令,學習到如何在WPF框架基礎上做一些封裝,如果可能甚至可以自己重新封裝一些功能更強大的命令來兼容Prism。