[Windows] Prism 8.0 入門(上):Prism.Core

      網友投稿 1270 2025-03-31

      1. Prism 簡介#

      Prism 是一個用于構建松耦合、可維護和可測試的 XAML 應用的框架,它支持所有還活著的基于 XAML 的平臺,包括 WPF、Xamarin Forms、WinUI 和

      Uwp

      Uno。Prism 提供了一組設計模式的實現,這些模式有助于編寫結構良好且可維護的 XAML 應用程序,包括 MVVM、依賴項注入、命令、事件聚合器等。

      Prism 是一個有10年以上歷史的框架,而上個月才剛發布了它的 8.0 版本,這意味著現在網上能找到的大部分 Prism 的資料都已經有點過時,連 官方文檔 也不例外。如果你需要詳細的文檔,除了官方文檔,我會推薦 RyzenAdorer 的 Prism 系列文章:

      NET Core 3 WPF MVVM框架 Prism系列文章索引 - RyzenAdorer -

      如果你不需要那么詳細的文檔,只需要一個入門的教程,那么我希望我寫的這兩篇文章可以幫到你。

      2. Prism.Core、Prism.Wpf 和 Prism.Unity

      從很久以前開始,臃腫 就是 Prism 被提起最多的標簽。畢竟比起 MVVMLight,Prism 實現的功能更多;對于初學者來說,剛打開 Prism 的文檔很可能會馬上選擇放棄。Prism 的文檔詳細到讓人望而卻步,例如多年前的舊版官方文檔的 其中一篇:

      不是 6 分鐘,不是 16 分賬,是整整 60 分鐘,Prism 的舊文檔隨便打開一篇都嚇死人。而 Prism 的各種包更是多到離譜。例如幾年前的 Prism 6.3,其中 WPF 平臺的項目有這么多個:

      Prism.Wpf

      Prism.Autofac

      Prism.DryIoc

      Prism.Mef

      Prism.Ninject

      Prism.StructureMap

      Prism.Unity

      所以臃腫是很多人對 Prism 的印象。

      減肥是一個永恒的受歡迎的話題,對 Prism 也是一樣。相比 Prism 6.3,剛剛發布的 8.0 已經好很多了(雖然還是有很多個項目),例如 WPF 平臺的項目已經大幅刪減,只保留了 Prism.Wpf、Prism.DryIoc 和 Prism.Unity,也就是說現在 Prism 只支持 DryIoc 和 Unity 兩種 IOC 容器。這樣一來 Prism 項目的結構就很清晰了。

      以 WPF 為例,核心的項目是 Prism.Core,它提供實現 MVVM 模式的核心功能以及部分各平臺公用的類。然后是 Prism.Wpf,它提供針對 Wpf 平臺的功能,包括導航、彈框等。最后由 Prism.Unity 指定 Unity 作為 IOC 容器。

      [Windows] Prism 8.0 入門(上):Prism.Core

      即使已精簡了這么多,Prism 還是有很多功能,兩篇文章也不足以講解全部內容,所以我只會介紹最常用到的入門知識。這篇文章首先介紹 Prism.Core 的主要功能。

      3. Prism.Core

      Prism.Core 可以單獨安裝,目前最新的版本是 8.0.0.1909:

      Install-Package Prism.Core -Version 8.0.0.1909

      除了一些各個平臺都用到的零零碎碎的公用類,作為一個 MVVM 庫 Prism.Core 主要提供了下面三方面的功能:

      BindableBase 和 ErrorsContainer

      Commanding

      Event Aggregator

      這些功能已經覆蓋了 MVVM 的核心功能,如果只需要與具體平臺無關的 MVVM 功能,可以只安裝 Prism.Core。

      4. BindableBase 和 ErrorsContainer#

      數據綁定是 MVVM 的核心元素之一,為了使綁定的數據可以和 UI 交互,數據類型必須繼承 INotifyPropertyChanged。 BindableBase 實現了 INotifyPropertyChanged 最簡單的封裝,它的使用如下:

      public class MockViewModel : BindableBase { private string _myProperty; public string MyProperty { get { return _myProperty; } set { SetProperty(ref _myProperty, value); } } }

      其中 SetProperty 判斷 _myProperty 和 value 是否相等,如果不相等就為 _myProperty 賦值并觸發 OnPropertyChanged 事件。

      除了 INotifyPropertyChanged,綁定機制中另一個十分有用的接口是 INotifyDataErrorInfo,它用于公開數據驗證的結果。Prism 提供了 ErrorsContainer 以便管理及通知數據驗證的錯誤信息。要使用 ErrorsContainer,可以先寫一個類似這樣的基類:

      public class DomainObject : BindableBase, INotifyDataErrorInfo { public ErrorsContainer _errorsContainer; protected ErrorsContainer ErrorsContainer { get { if (_errorsContainer == null) _errorsContainer = new ErrorsContainer(s => OnErrorsChanged(s)); return _errorsContainer; } } public event EventHandler ErrorsChanged; public void OnErrorsChanged(string propertyName) { ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName)); } public IEnumerable GetErrors(string propertyName) { return ErrorsContainer.GetErrors(propertyName); } public bool HasErrors { get { return ErrorsContainer.HasErrors; } } }

      然后就可以在派生類中通過 ErrorsContainer.SetErrors 和 ErrorsContainer.ClearErrors 管理數據驗證的錯誤信息:

      public class MockValidatingViewModel : DomainObject { private int mockProperty; public int MockProperty { get { return mockProperty; } set { SetProperty(ref mockProperty, value); if (mockProperty < 0) ErrorsContainer.SetErrors(() => MockProperty, new string[] { "value cannot be less than 0" }); else ErrorsContainer.ClearErrors(() => MockProperty); } } }

      5. Commanding

      ICommand 同樣是 MVVM 模式的核心元素,DelegateCommand 實現了 ICommand 接口,它最基本的使用形式如下,其中 DelegateCommand 構造函數中的第二個參數 canExecuteMethod 是可選的:

      public DelegateCommand SubmitCommand { get; private set; } public CheckUserViewModel() { SubmitCommand = new DelegateCommand(Submit, CanSubmit); } private void Submit() { //implement logic } private bool CanSubmit() { return true; }

      另外它還有泛型的版本:

      public DelegateCommand SubmitCommand { get; private set; } public CheckUserViewModel() { SubmitCommand = new DelegateCommand(Submit, CanSubmit); } private void Submit(string parameter) { //implement logic } private bool CanSubmit(string parameter) { return true; }

      通常 UI 會根據 ICommand 的 CanExecute 函數的返回值來判斷觸發此 Command 的 UI 元素是否可用。CanExecute 返回 DelegateCommand 構造函數中的第二個參數 canExecuteMethod 的返回值。如果不傳入這個參數,則 CanExecute 一直返回 True。

      如果 CanExecute 的返回值有變化,可以調用 RaiseCanExecuteChanged 函數,它會觸發 CanExecuteChanged 事件并通知 UI 元素重新判斷綁定的 ICommand 是否可用。除了主動調用 RaiseCanExecuteChanged,DelegateCommand 還可以用 ObservesProperty 和 ObservesCanExecute 兩種形式監視屬性,定于屬性的 PropertyChanged 事件并改變 CanExecute:

      private bool _isEnabled; public bool IsEnabled { get { return _isEnabled; } set { SetProperty(ref _isEnabled, value); } } private bool _canSave; public bool CanSave { get { return _canSave; } set { SetProperty(ref _canSave, value); } } public CheckUserViewModel() { SubmitCommand = new DelegateCommand(Submit, CanSubmit).ObservesProperty(() => IsEnabled); //也可以寫成串聯方式 SubmitCommand = new DelegateCommand(Submit, CanSubmit).ObservesProperty(() => IsEnabled).ObservesProperty(() => CanSave); SubmitCommand = new DelegateCommand(Submit).ObservesCanExecute(() => IsEnabled); }

      6. Event Aggregator#

      本來Event Aggregator(事件聚合器)或 Messenger 之類的組件本來并不是 MVVM 的一部分,不過現在也成了 MVVM 框架的一個重要元素。解耦是 MVVM 的一個重要目標,'EventAggregator' 則是實現解耦的重要工具。在 MVVM 中,對于 View 和與他匹配的 ViewModel 之間的交互,可以使用 INotifyProperty 和 Icommand;而對于必須通信的不同 ViewModel 或模塊,為了使它們之間實現低耦合,可以使用 Prism 中的 EventAggregator。如下圖所示,Publisher 和 Scbscriber 之間沒有直接關聯,它們通過 Event Aggregator 獲取 PubSubEvent 并發送及接收消息:

      要使用 EventAggregator,首先需要定義 PubSubEvent:

      public class TickerSymbolSelectedEvent : PubSubEvent{}

      發布方和訂閱方都通過 EventAggregator 索取 PubSubEvent,在 ViewModel中通常都是通過依賴注入獲取一個 IEventAggregator:

      public class MainPageViewModel { IEventAggregator _eventAggregator; public MainPageViewModel(IEventAggregator ea) { _eventAggregator = ea; } }

      發送方的操作很簡單,只需要 通過 GetEvent 拿到 PubSubEvent,把消息發布出去,然后拍拍屁股走人,其它的責任都不用管:

      _eventAggregator.GetEvent().Publish("STOCK0");

      訂閱方是真正使用這些消息并負責任的人,下面是最簡單的通過 Subscribe 訂閱事件的代碼:

      public class MainPageViewModel { public MainPageViewModel(IEventAggregator ea) { ea.GetEvent().Subscribe(ShowNews); } void ShowNews(string companySymbol) { //implement logic } }

      除了基本的調用方式,Subscribe 函數還有其它可選的參數:

      public virtual SubscriptionToken Subscribe(Action action, ThreadOption threadOption, bool keepSubscriberReferenceAlive)

      其中 threadOption 指示收到消息后在哪個線程上執行第一個參數定義的 action,它有三個選項:

      PublisherThread,和發布者保持在同一個線程上執行。

      UIThread,在 UI 線程上執行。

      BackgroundThread,在后臺線程上執行。

      第三個參數 keepSubscriberReferenceAlive 默認為 false,它指示該訂閱是否為強引用。

      設置為 false 時,引用為弱引用,用完可以不用管。

      設置為 true 時,引用為強引用,用完需要使用 Unsubscribe 取消訂閱。

      下面代碼是一段訂閱及取消訂閱的示例:

      public class MainPageViewModel { TickerSymbolSelectedEvent _event; public MainPageViewModel(IEventAggregator ea) { _event = ea.GetEvent(); _event.Subscribe(ShowNews); } void Unsubscribe() { _event.Unsubscribe(ShowNews); } void ShowNews(string companySymbol) { //implement logic } }

      7. 生產力工具

      如果覺得屬性和 DelegateCommand 的定義有些啰嗦,可以試試安裝這個工具:Prism Template Pack,它提供了一些實用的代碼段和一些 Project 和 Item 的模板。例如,安裝此工具后可以通過 cmd 代碼段快速生成一個完整的 DelegateCommand 代碼:

      private DelegateCommand _fieldName; public DelegateCommand CommandName => _fieldName ?? (_fieldName = new DelegateCommand(ExecuteCommandName)); void ExecuteCommandName() { }

      更多代碼段定義請參考官方文檔:Productivity Tools Prism

      8. 結語

      Prism.Core 最初由 Microsoft Patterns and Practices 團隊創建,現在轉移到社區。雖然 Prism 框架非常成熟(還有點臃腫),支持插件和定位控件的區域,但 Prism.Core 很輕,僅包含幾個常用的類型。這篇文章已經把 Prism.Core 中最常用的類盡可能簡單地介紹過一遍,這足夠用完創建一個基于 MVVM 框架的項目。

      Prism 的更多功能將在下一篇文章中介紹。

      9. 參考

      https://github.com/PrismLibrary/Prism

      https://prismlibrary.com/docs/index.html

      INotifyPropertyChanged 接口

      INotifyDataErrorInfo 接口

      ICommand 接口

      出處:https://www.cnblogs.com/dino623/p/using_prism_core.html

      版權:本文采用「CC BY 4.0」知識共享許可協議進行許可。

      WPF

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:紙箱生產系統的設計(紙箱生產過程及工藝介紹)
      下一篇:怎樣刪除空白文檔(怎樣刪除空白文檔最后一頁)
      相關文章
      亚洲高清美女一区二区三区| 久久精品国产精品亚洲| 久久久久亚洲精品中文字幕| 亚洲国产美女精品久久久 | 亚洲精品影院久久久久久| 亚洲精品视频在线免费| 亚洲第一精品在线视频| 久久久久亚洲精品美女| 亚洲成年轻人电影网站www| 亚洲av一综合av一区| 久久精品国产精品亚洲蜜月| 亚洲动漫精品无码av天堂| 国产成人亚洲精品播放器下载 | 亚洲国产精品久久久久秋霞小| 亚洲真人无码永久在线观看| 国产亚洲精品影视在线| 亚洲日韩AV一区二区三区四区| 久久久亚洲欧洲日产国码aⅴ| 亚洲一级片内射网站在线观看| 亚洲v国产v天堂a无码久久| 亚洲国产精品成人网址天堂 | 精品亚洲视频在线| 国产偷国产偷亚洲高清人| 亚洲成a人片在线播放| 久久亚洲精品无码观看不卡| 在线精品亚洲一区二区小说| 黑人精品videos亚洲人| 亚洲电影国产一区| 亚洲熟妇av一区二区三区下载| 亚洲avav天堂av在线网爱情| 亚洲一区二区三区丝袜| 精品国产_亚洲人成在线| 亚洲综合色视频在线观看| 亚洲精品无码成人AAA片| 久久亚洲一区二区| 亚洲欧洲高清有无| 亚洲日本成本人观看| 亚洲成A人片在线观看无码3D | 亚洲综合小说久久另类区| 亚洲免费在线视频观看| 亚洲国产成人综合精品|