一、簡介
WPF Prism是一套由微軟模式和實踐團隊(Microsoft Patterns & Practices Team)開發的面向Windows Presentation Foundation (WPF) 的框架。該框架目標是帶來可重用、可插入、可測試的模塊化代碼,以及保持松耦合的應用程序代碼。WPF Prism框架用於幫助開發人員構建具有高度模塊化、可測試、可維護且易於擴展的WPF桌面應用程序。Prism利用依賴注入 (DI) 容器來實現模塊化、命令、事件聚合 (EA)、導航、區域等功能,以提供一致性的解決方案。
二、模塊化開發
設計良好的應用程序應該是由若干松耦合的模塊組成的,每個模塊都能獨立、可移植、可重用,並且易於測試。Prism框架通過依賴注入(DI)容器實現模塊化,代碼創建對象時只需指定對象基類或介面,DI容器會自動尋找並構造該對象所依賴的實例,並返回完整的對象。
實際上,在Prism框架上,模塊等同於程序集,而且每個程序集都必須包含一個派生自 IModule
介面的模塊類。這個類需要實現 IModule.Initialize
方法,通過該方法可以向程序注入一些功能。下面介紹一些重要的基本模塊初始化,以及在模塊之間共享數據。
1. 模塊初始化
使用Prism框架,您可以使用以下代碼,初始化模塊
// MyApp.ModulA.dll
public class ModulA : IModule
{
public void Initialize()
{
// 初始化視圖和服務所需的代碼
}
}
// App.xaml.cs
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// 使用RegisterType註冊服務
containerRegistry.RegisterType<IService, Service>();
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
// 使用ModuleCatalog添加模塊
moduleCatalog.AddModule(typeof(ModulA));
}
2. 模塊間共享數據
在模塊之間,有時需要共享數據。例如,ModulA
模塊需要提供數據,以便其他模塊使用,您可以使用以下代碼,向其他需要該數據的模塊添加服務
// MyApp.ModulA.dll
public class ModulA : IModule
{
// 公共數據
public static IData Data = new Data();
public void Initialize()
{
// 註冊服務
containerRegistry.RegisterInstance<IData>(Data);
}
}
// MyApp.ModulB.dll
public class ModulB : IModule
{
public ModulB(IData data)
{
var myData = data as Data;// 編寫代碼,以便使用Data服務
}
public void Initialize()
{
// 初始化...
}
}
// App.xaml.cs
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<ModulA>();// 我們不需要在此處添加ModulB,因為ModulB是自動載入的
}
三、依賴注入
依賴注入(Dependency Injection)是一種編程方法,通過該方法,我們可以創建松耦合、可測試且可重用的代碼。您只需定義介面或基類,然後使用Prism框架,自動尋找並創建該介面或基類的實現。依賴注入是Prism框架的核心,貫穿整個框架。
1. 構造函數注入
構造函數注入是最簡單的依賴注入方法。在該模式下,您僅需使用 Container.Resolve
方法創建實例。以下代碼演示使用構造函數注入實例化對象
// 定義介面和實現
public interface IService
{
void DoSomething();
}
public class Service : IService
{
public void DoSomething()
{
Console.WriteLine("Hello World!");
}
}
// Main
var service = Container.Resolve<IService>();
service.DoSomething();
2. 屬性注入
屬性注入是一種廣泛應用的依賴注入方法。該方法在對象創建完成之後,通過反射操作,向對象的屬性自動注入相應的實現實例。通過Prism框架,我們使用 [Dependency]
特性注入屬性。
// 定義介面和實現
public interface IService
{
void DoSomething();
}
public class Service : IService
{
public void DoSomething()
{
Console.WriteLine("Hello World!");
}
}
// Main
class MainViewModel
{
[Dependency]
public IService Service { get; set; } // 必須是公共屬性
public MainViewModel()
{
}
public void DoSomething()
{
Service.DoSomething();
}
}
// 在Main函數中初始化
var mainViewModel = new MainViewModel();
Container.BuildUp(mainViewModel); // 執行依賴注入
mainViewModel.DoSomething();
四、命令
在Prism框架中,命令(Command)是一項非常強大的功能,它可以輕鬆解決許多典型的WPF應用程序需求,例如向視圖添加命令,創建分離的命令對象,將命令綁定到控制項或 ViewModel 等。
在Prism框架內部,命令使用 DelegateCommand / DelegateCommand<T>
類來實現。例如,以下是使用 DelegateCommand
類創建命令的示例代碼
// 定義命令
public DelegateCommand MyCommand { get; private set; }
public MainViewModel()
{
// 添加命令
MyCommand = new DelegateCommand(Execute, CanExecute);
}
void Execute()
{
Debug.WriteLine("執行命令");
}
bool CanExecute()
{
return true;
}
五、導航
在WPF應用程序中,導航(navigation)是一項關鍵的功能。該功能使我們能夠通過顯示給定的頁面或視圖,讓用戶在視覺上移動,以便在不同的屏幕之間進行切換。在Prism框架中,導航需要兩個主要組件: 導航器(NavigationService)和導航目的地(NavigationTarget)。
導航器處理導航請求,而導航目的地則對導航請求進行響應。
// 在模塊中添加導航
public class AppModule : IModule
{
public AppModule(INavigationService navigationService)
{
this.navigationService = navigationService;
}
public void Initialize()
{
navigationService.RegisterViewWithRegion("MainRegion", typeof(ViewA));
}
}
// 在ViewModel中實現導航
public class ViewAViewModel : BindableBase // BindableBase是Prism中的一個基類,實現了 INotifyPropertyChanged
{
public ViewAViewModel(INavigationService navigationService)
{
NavigateCommand = new DelegateCommand(() => navigationService.Navigate("ViewB"));
}
private DelegateCommand _navigateCommand;
public DelegateCommand NavigateCommand
{
get => _navigateCommand;
set => SetProperty(ref _navigateCommand, value);
}
}
// 在View中,創建一個按鈕並將它綁定到導航命令
// 顯示View
navigationService.Navigate("ViewA");
六、區域
在WPF Prism中,區域(Region)是指一個可以在其中顯示一個或多個視圖的窗體區域。您可以將區域視為桌面應用程序中的子窗口,因為您可以將視圖放入區域,並在不同的區域中切換視圖。
以下示例演示如何創建區域,並將視圖添加到該區域
// App.xaml.cs
public partial class App : PrismApplication
{
protected override Control CreateShell()
{
return Container.Resolve();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.Register();
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule();
}
protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
{
base.ConfigureRegionAdapterMappings(regionAdapterMappings);
regionAdapterMappings.RegisterMapping(typeof(StackPanel), Container.Resolve());
}
}
// 註冊StackPanel區域和Adapter
public class StackPanelRegion : Region
{
}
public class StackPanelRegionAdapter : IRegionAdapter
{
public IRegion Initialize(object regionTarget, string regionName)
{
var region = new StackPanelRegion();
region.Name = regionName;
var stackpanel = regionTarget as StackPanel;
RegionManager.SetRegionManager(stackpanel, ContainerLocator.Current.Resolve());
RegionManager.UpdateRegions();
return region;
}
public bool IsAdaptable(object regionTarget)
{
return regionTarget is StackPanel;
}
public void AdaptView(object regionTarget)
{
}
}
// 主模塊
public class MainModule : IModule
{
public void Initialize()
{
IRegionManager regionManager = ServiceLocator.Current.GetInstance();
regionManager.RegisterViewWithRegion("TopArea", typeof(TopView));
}
}
// 創建具有指定名稱的區域,以及包含「TopArea」名稱的StackPanel控制項
七、總結
通過本文的介紹,我們可以看到WPF Prism框架的強大功能:模塊化開發、依賴注入、命令、導航和區域。通過這些功能,我們可以輕鬆地構建可擴展、可重用、可測試的WPF應用程序。當然,除了本文介紹的這些內容之外,WPF Prism框架還提供了許多其他的功能和特性,如事件聚合(event aggregator),屬性注入、策略等。
原創文章,作者:YRTWS,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/372072.html