1. 程式人生 > >Prism 原始碼解讀5-資料繫結和命令

Prism 原始碼解讀5-資料繫結和命令

## 介紹 WPF本身就支援通知、繫結和命令,實現ViewModel和VIew之間的通訊,但相對來說功能比較少,Prism擴充了這些功能並提供更加強有力,簡潔的資料繫結和命令。 ## 0 繫結通知 WPF的繫結通知需要實現INotifyPropertyChanged介面,也就是實現一個屬性改變事件,用來通知UI屬性改變了,讓UI更新。該事件需要一個事件引數new PropertyChangedEventArgs(propertyName)傳入屬性的名字,這樣的呼叫方式比較繁瑣。 Prism擴充了WPF的繫結通知。提供了BindableBase 實現了 INotifyPropertyChanged介面,並使用CallerMemberName獲取屬性名字。這樣就解決了屬性改變事件呼叫繁瑣的問題。同時在內部還是對相等值進行了過濾。 ![1585984101837](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708843-1702991048.png) ![1585985493521](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708877-1354432512.png) 簡單愉快的呼叫吧 ![1585985633084](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708878-1901199377.png) 只需要使用SetProperty方法就可以自動更新UI了。 值得注意的是OnPropertyChanged還提供了對Expression的支援 ![1585986210800](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708877-568046699.png) 也就是主動呼叫OnPropertyChanged(()=>this.PropertyName),也可以觸發UI響應。 ## 1 命令 ### DelegateCommand WPF命令和通知有點類似,命令需要實現ICommand介面,實現Execute方法,命令狀態CanExecute和命令狀態改變事件。並且WPF只實現了一個RoutedCommand。Prism提供了一個DelegateCommandBase命令基類實現ICommand,並擴充了子類DelegateCommand,大大簡化了命令呼叫方式 ![1585982600756](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708879-1353104735.png) ![1585982617542](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708877-954606042.png) 看到在基類中有_synchronizationContext執行緒同步上下文,用來保證命令執行的時候執行緒同步。 重點關注一下子類中的幾個方法 ![1585987365575](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708878-1142200719.png) ![1585987399505](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708877-459954683.png) ![1585987411359](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708878-2100159727.png) 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(ExecuteGeneric).ObservesCanExecute(() => IsEnabled); - 這是一個使用泛型帶引數的宣告方式, 看一下內部怎麼實現這種簡單而強大的功能 ![1585988022789](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708878-184586764.png) ![1585988063481](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708878-2099308553.png) 通過Expression,內部呼叫PropertyObserver.Observes()方法並將RaiseCanExecuteChaned方法傳入。 在PropertyObserver將Expression儲存在一個連結串列,並每個節點都訂閱OnPropertyChanged事件。 ![1585988408971](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708844-977515147.png) ### CompositeCommand Prism還提供了一個CompositeCommand命令 ![1585989655012](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708879-975859313.png) 這個命令的功能跟其名字一樣,就是複合命令,命令集合。 - 將DelegateCommand例項放到其中,每當呼叫CompositeCommand呼叫的時候會呼叫它儲存的所有命令, - 命令集合中任何一個命令狀態改變,都會觸發CompositeCommand命令狀態的改變事件,導致CompositeCommand檢查集合中所有的命令狀態,首先會檢查IActiveAware,再檢查命令狀態,如果任何一個命令狀態是False,都會導致組合命令返回False 來看一下原始碼 ![1585989673663](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708879-1481801842.png) ![1585989692622](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708880-760043693.png) ![1585989705258](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708914-1826322243.png) 注意到,聚合命令也是通過執行緒上下文保持執行緒同步,同時看到有檢測IActiveAware介面,這個介面是什麼意思呢?其實就是檢視該命令是否啟用。這個介面有一個啟用狀態屬性和一個啟用狀態改變事件, ![1585989967522](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708915-1986517383.png) 只要介面主動呼叫UpdateCommand.IsActive = true;命令就會被啟用並觸發複合命令的啟用狀態改變回調函式 ![1586001088755](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708915-1762675636.png) ![1586001120188](https://img2020.cnblogs.com/blog/1078802/202004/1078802-20200404201708915-1670037345.png) 在複合命令的ShouldExcute方法中檢查其啟用狀態,命令集合中沒有啟用命令,那麼複合命令的執行狀態也會改變。 命令執行和啟用狀態都是差不多的介面,有狀態和狀態改變事件組成,感覺很多地方都有相似的模式,有點像訂閱模式,也有點像狀態機,包括一些Collection和Storage. ## 總結 主要講了下Prism提供的繫結通知和命令,學習到如何在WPF框架基礎上做一些封裝,如果可能甚至可以自己重新封裝一些功能更強大的命令來相容