WPF Prism 3 - 首次使用 Module 與 Prism 開發框架來製作一個 Hello World 教學說明程式
在這篇文章,將會使用 Prism 中的 Module 模組功能,實作第一篇文章的 Hello World 相同功能,因此,在這裡將會建立一個類別庫,將相關 View & ViewModel 都建立在這個類別庫內。
這個說明專案的原始碼位於 WPFPrismHelloWorldWithModule
準備工作
- 首先,先要安裝 [Prism Template Pack] 到 Visual Studio 2019 內
- 打開 Prism Template Pack 擴充功能網站
- 下載並且安裝這個擴充功能
建立 WPF for Prism 的專案
- 打開 Visual Studio 2019
- 點選右下方的 [建立新的專案] 按鈕
- [建立新專案] 對話窗將會顯示在螢幕上
- 從[建立新專案] 對話窗的中間區域,找到 [Prism Blank App (WPF)] 這個專案樣板選項,並且選擇這個項目若沒有看到這個選項,則表示你的 Visual Studio 2019 開發環境中,還沒有安裝 Prism Template Pack 擴充功能
- 點選右下角的 [下一步] 按鈕
- 現在 [設定新的專案] 對話窗將會出現
- 請在這個對話窗內,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱]在這裡請輸入 [專案名稱] 為
WPFPrismHelloWorld
- 在最下方的 [架構] 部分,建議選取最新的 [.NET Framework 4.8]
- 完成後,請點選 [建立] 按鈕
- 當出現 [PRISM PROJECT WIZARD] 對話窗的時候
- 請在 [Select Container] 選擇容器這個欄位之下拉選單,選擇你要使用的 DI 相依性注入容器,我個人習慣使用 Unity 這個 Ioc 容器
- 之後,點選 [CREATE PROJECT] 這個按鈕
稍微等會一段時間,具有 Prism 開發框架的 WPF 專案將會建立起來
建立要設計 Module 的類別庫專案 - WPF 使用者控制項類別庫 (.NET Framework)
- 滑鼠右擊方案節點,選擇 [加入] > [新增專案]
- 當 [新增專案] 對話出現之後
- 找到並且點選 [WPF 使用者控制項類別庫 (.NET Framework)]
請注意
這裡需要找到的是 使用 C# 程式語言,並且是 .NET Framework 用的 [WPF 使用者控制項類別庫 (.NET Framework)],這不是一般的 [類別庫 (.NET Framework)] - 選擇完後,點選 [下一步] 按鈕
- 在 [專案名稱] 欄位中,輸入
HostModule
- 點選 [建立] 按鈕
加入 WPF 套件
- 滑鼠右擊剛剛建立的專案節點
- 選擇 [管理 NuGet 套件]
- 找到 [Prism.Wpf] 這個套件,並且安裝起來
在剛剛建立的專案中,加入兩個 View 與進行 Module 類別設計
- 滑鼠右擊剛剛建立的專案,選擇 [加入] > [新增資料夾],建立
Views
&ViewModels
這兩個資料夾 - 滑鼠右擊 [Views] 資料夾
- 選擇 [加入] > [新增項目]
- 此時,[新增項目] 對話窗將顯示出來
- 請在該對話窗的左方,展開節點到 [已安裝] > [Visual C#] > [Prism] > [WPF]
- 在中間區域選擇 [Prism UserControl (WPF)] 選項
- 在下方名稱欄位輸入
MyView
- 最後點選 [新增] 按鈕
此時,將會看到該專案的 [Views] 資料夾內新產生了一個 [MyView.xaml] 這個檔案,另外,在 [ViewModel] 資料夾內也產生了一個 [MyViewViewModel] 這個類別檔案。
打開 [MyView.xaml] 檔案,填入底下 XAML 標記宣告
<UserControl x:Class="HostModule.Views.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid Background="LightGreen">
<TextBlock Text="Hello World" FontSize="48" Foreground="HotPink"/>
</Grid>
</UserControl>
接下來,繼續產生一個 YourView 檢視
- 首先,滑鼠右擊 [Views] 資料夾
- 選擇 [加入] > [新增項目]
- 此時,[新增項目] 對話窗將顯示出來
- 請在該對話窗的左方,展開節點到 [已安裝] > [Visual C#] > [Prism] > [WPF]
- 在中間區域選擇 [Prism UserControl (WPF)] 選項
- 在下方名稱欄位輸入
YourView
- 最後點選 [新增] 按鈕
此時,將會看到該專案的 [Views] 資料夾內新產生了一個 [YourView.xaml] 這個檔案,另外,在 [ViewModel] 資料夾內也產生了一個 [YourViewViewModel] 這個類別檔案。
打開 [YourView.xaml] 檔案,填入底下 XAML 標記宣告
<UserControl x:Class="HostModule.Views.YourView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid Background="Yellow">
<TextBlock Text="Thank You" FontSize="48" Foreground="LightBlue"/>
</Grid>
</UserControl>
- 滑鼠右擊這個專案節點,選擇 [加入] > [類別]
- 當 [新增項目] 對話窗出現後,在下方的 [名稱] 欄位中輸入
HostModuleModule
- 將底下的 C# 程式碼,替換掉剛剛產生的檔案內容
using HostModule.Views;
using Prism.Ioc;
using Prism.Modularity;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HostModule
{
public class HostModuleModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<MyView>();
containerRegistry.RegisterForNavigation<YourView>();
}
}
}
修正主專案並加入這個模組
- 滑鼠右擊主專案 (也就是這個 WPFPrismHelloWorldWithModule 專案) 內的 [參考] > [加入參考]
- 當 [參考管理員] 對話窗出現之後,勾選 [HostModule] 這個節點
- 點選 [確定] 按鈕
- 在該專案根目錄下,找到 App.xaml 這個檔案節點
- 展開該節點,將會看到一個 [App.xaml.cs] 這個節點
- 滑鼠雙擊打開 [App.xaml.cs] 這個節點
- 建立一個覆寫 ConfigureModuleCatalog 方法
- 將該方法修改成為底下的程式碼
using WPFPrismHelloWorldWithModule.Views;
using Prism.Ioc;
using Prism.Modularity;
using System.Windows;
namespace WPFPrismHelloWorldWithModule
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
moduleCatalog.AddModule<HostModule.HostModuleModule>();
}
}
}
設計 Shell 頁面架構
- 在 [Views] 資料夾內,找到並打開 [MainWindow.xaml] 檔案
- 將底下的 XAML 標記宣告,替換掉這個檔案原先內容
<Window x:Class="WPFPrismHelloWorldWithModule.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525">
<Grid Background="LightGray">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button Command="{Binding SayHiCommand}" Width="150">Hi</Button>
<Button Command="{Binding ThankYouCommand}" Width="150">Thank You</Button>
<Button Command="{Binding RemoveCommand}" Width="150">Remove</Button>
</StackPanel>
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
- 在 [ViewModels] 資料夾內,找到並打開 [MainWindowViewModel.cs] 檔案
- 使用底下 C# 程式碼替換掉原先內容
using HostModule.Views;
using Prism.Commands;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
namespace WPFPrismHelloWorldWithModule.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "Prism Application";
private readonly IRegionManager regionManager;
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public DelegateCommand SayHiCommand { get; set; }
public DelegateCommand RemoveCommand { get; set; }
public DelegateCommand ThankYouCommand { get; set; }
public MainWindowViewModel(IRegionManager regionManager, IContainerExtension container)
{
SayHiCommand = new DelegateCommand(() =>
{
IRegion region = regionManager.Regions["ContentRegion"];
region.RemoveAll();
var view = container.Resolve<MyView>();
region.Add(view);
});
ThankYouCommand = new DelegateCommand(() =>
{
IRegion region = regionManager.Regions["ContentRegion"];
region.RemoveAll();
var view = container.Resolve<YourView>();
region.Add(view);
});
RemoveCommand = new DelegateCommand(() =>
{
IRegion region = regionManager.Regions["ContentRegion"];
region.RemoveAll();
});
}
}
}
執行與測試
現在可以執行這個使用 Prism 開發的 WPF 專案,看看是不是如同第一篇文章規劃的一樣方式來進行運作。