前兩章中, 我們已經實作了這個圖書管理系統的登入視窗, 并實施了完善的單元測試. 該是時候回過頭來關注我們的主視窗了.
一個功能豐富的系統一般會有多個頁面, 我們圖書管理系統雖然是"簡易"的, 但是同樣也有多個頁面. 是以這一章中, 我們來學習如何使用Stylet的Conductor來管理頁面的切換.
事實上, 第一章使用的 IWindowManager.ShowDialog
彈出的登入視窗也可視為一個頁面. 但是據我的個人經驗, 我更推薦将所有頁面放在一個視窗中, 這樣更友善實施MVVM. 這章過後,你可嘗試使用Conductor來顯示登入頁面.
Conductor翻譯過來是指揮的意思, 在Stylet中Conductor就是用來指揮各個ViewModel的, 因為一般在MVVM中ViewModel代表一個頁面, 是以Conductor通過管理ViewModel來實作頁面的狀态的管理. Stylet内置了多種Conductor, 适用于不同的使用場景, 這裡做一個簡要的介紹:
Conductor | 使用場景 |
---|---|
| 最簡單的Conductor, 隻管理一個頁面 |
| 管理多個頁面, 但隻顯示其中的一個. 最典型場景如一個TabControl控件 |
| 管理多個頁面, 并且全部顯示. 典型場景如一個ItemControl控件 |
| 管理多個頁面, 隻顯示其中一個, 但保留了之前顯示頁面的曆史可用于回退. 典型場景如一個向導頁面, 允許使用者通過"上一步", "下一步"切換 |
更多關于Conductor的資訊, 可參見Stylet的官方WIKI: Screens and Conductors
在本章中, 我們想要顯示兩個頁面: "首頁"和"圖書"頁面, 因為在同一時間隻會顯示其中一個, 是以使用
Conductor<T>
就可以了. 下面就開始我們的CODING工作:
增加首頁
在Page檔案夾中建立一個名為"Home"的檔案夾, 并建立一個C#類:
HomeViewModel
和一個UserControl:
HomeView
, 用來顯示我們系統的首頁.
- 将
的基類設定為HomeViewModel
:Screen
因為Home中沒有任何邏輯, 是以不需要任何其他代碼.public class HomeViewModel : Screen { }
- 在
的XAML中增加以下XAML代碼:HomeView
<UserControl x:Class="StyletBookStore.Pages.Home.HomeView" ... > <Grid> <TextBlock FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center"> 歡迎使用簡易圖書管理系統 </TextBlock> </Grid> </UserControl>
改造Shell
-
的基類改為ShellViewModel
Conductor<Screen>
這樣public class ShellViewModel : Conductor<Screen> { ... }
就變成了一個可管理單一頁面的Conductor了, 而且每個頁面都需要是ShellViewModel
的子類.Screen
- 因為我們将所有顯示部分放在各自的頁面中, 是以将
中ShellView
中的XAML完全删除, 并替換為以下代碼.<Window>...</Window>
<Window x:Class="StyletBookStore.Pages.ShellView" ... Title="簡易圖書管理系統"> <ContentControl s:View.Model="{Binding ActiveItem}"/> </Window>
-
設定為我們的系統名字: "簡易圖書管理系統"Title
- 增加一個
用來顯示頁面内容.ContentControl
-
是Stylet提供的附加屬性, 用來為View綁定Models:View.Model
-
是ActiveItem
的一個屬性, 就是該Conductor的目前的頁面. 因為Conductor<T>
繼承了ShellViewModel
, 是以在Conductor<T>
中可以綁定該屬性.ShellView
-
-
顯示首頁
如果你現在啟動程式, 會發現程式可以正常啟動, 但是Shell中不會顯示任何内容. 這是因為我們未給
ShellViewModel
這個Conductor設定ActiveItem.
ShellViewModel
的
OnViewLoaded
方法的開始位置, 增加以下代碼, 用來在程式啟動時就顯示首頁.
protected override void OnViewLoaded()
{
// 顯示首頁
var homeViewModel = _container.Get<HomeViewModel>();
ActivateItem(homeViewModel);
// 顯示登入視窗
...
}
ActivateItem
方法是
Condocutor<T>
中提供的方法.用一個新的ViewModel執行個體替換目前的
ActiveItem
,激活新的頁面并關閉舊的. 我們使用該方法即可實作頁面的切換.
再次啟動程式, 确認首頁已經能正常顯示了:
顯示圖書頁面
- Page檔案夾中建立一個名為"Books"的檔案夾, 并建立一個C#類:
IndexViewModel
, 用來顯示圖書清單頁面: 要點如下:IndexView
-
IndexViewModel
Screen
-
中增加一個IndexView
用來(暫時)辨別這是圖書頁面:TextBlock
<TextBlock Text="IndexView"/>
-
- 同樣, 在
ShellViewModel
方法的末尾位置, 增加以下代碼, 用來在登入成功後, 切換到圖書頁面:OnViewLoaded
protected override void OnViewLoaded()
{
// 顯示首頁
var homeViewModel = _container.Get<HomeViewModel>();
ActivateItem(homeViewModel);
// 顯示登入視窗
...
// 顯示圖書
var indexViewModel = _container.Get<IndexViewModel>();
ActivateItem(indexViewModel);
}
再次使用
ActivateItem
方法, 将圖書的ViewModel切換進來. 再次啟動程式, 确認當登入成功後, 主視窗的頁面會切換到圖書頁面.(目前隻顯示一個IndeView, 我們會在下一章完善該頁面的功能)
本篇到此為止, 希望朋友們能多多留言, 鼓勵我能繼承寫下去. 源碼托管在GITHUB上.
Happy Coding~