天天看點

【WPF on .NET Core 3.0】 Stylet示範項目 - 簡易圖書管理系統(3) - 使用Conductor切換頁面

前兩章中, 我們已經實作了這個圖書管理系統的登入視窗, 并實施了完善的單元測試. 該是時候回過頭來關注我們的主視窗了.

一個功能豐富的系統一般會有多個頁面, 我們圖書管理系統雖然是"簡易"的, 但是同樣也有多個頁面. 是以這一章中, 我們來學習如何使用Stylet的Conductor來管理頁面的切換.

事實上, 第一章使用的

IWindowManager.ShowDialog

彈出的登入視窗也可視為一個頁面. 但是據我的個人經驗, 我更推薦将所有頁面放在一個視窗中, 這樣更友善實施MVVM. 這章過後,你可嘗試使用Conductor來顯示登入頁面.

Conductor翻譯過來是指揮的意思, 在Stylet中Conductor就是用來指揮各個ViewModel的, 因為一般在MVVM中ViewModel代表一個頁面, 是以Conductor通過管理ViewModel來實作頁面的狀态的管理. Stylet内置了多種Conductor, 适用于不同的使用場景, 這裡做一個簡要的介紹:

Conductor 使用場景

Conductor<T>

最簡單的Conductor, 隻管理一個頁面

Conductor<T>.Collection.OneActive

管理多個頁面, 但隻顯示其中的一個. 最典型場景如一個TabControl控件

Conductor<T>.Collection.AllActive

管理多個頁面, 并且全部顯示. 典型場景如一個ItemControl控件

Conductor<T>.StackNavigation

管理多個頁面, 隻顯示其中一個, 但保留了之前顯示頁面的曆史可用于回退. 典型場景如一個向導頁面, 允許使用者通過"上一步", "下一步"切換
更多關于Conductor的資訊, 可參見Stylet的官方WIKI: Screens and Conductors

在本章中, 我們想要顯示兩個頁面: "首頁"和"圖書"頁面, 因為在同一時間隻會顯示其中一個, 是以使用

Conductor<T>

就可以了. 下面就開始我們的CODING工作:

增加首頁

在Page檔案夾中建立一個名為"Home"的檔案夾, 并建立一個C#類:

HomeViewModel

和一個UserControl:

HomeView

, 用來顯示我們系統的首頁.

【WPF on .NET Core 3.0】 Stylet示範項目 - 簡易圖書管理系統(3) - 使用Conductor切換頁面
  • HomeViewModel

    的基類設定為

    Screen

    :
    public class HomeViewModel : Screen
        {
        }
               
    因為Home中沒有任何邏輯, 是以不需要任何其他代碼.
  • HomeView

    的XAML中增加以下XAML代碼:
    <UserControl x:Class="StyletBookStore.Pages.Home.HomeView"
        ...
        >
        <Grid>
            <TextBlock FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center">
                歡迎使用簡易圖書管理系統
            </TextBlock>
        </Grid>
    </UserControl>
    
               

改造Shell

  1. ShellViewModel

    的基類改為

    Conductor<Screen>

    public class ShellViewModel : Conductor<Screen>
        {
            ...
        }
               
    這樣

    ShellViewModel

    就變成了一個可管理單一頁面的Conductor了, 而且每個頁面都需要是

    Screen

    的子類.
  2. 因為我們将所有顯示部分放在各自的頁面中, 是以将

    ShellView

    <Window>...</Window>

    中的XAML完全删除, 并替換為以下代碼.
    <Window x:Class="StyletBookStore.Pages.ShellView"
        ...
        Title="簡易圖書管理系統">
        <ContentControl s:View.Model="{Binding ActiveItem}"/>
    </Window>
               
    • Title

      設定為我們的系統名字: "簡易圖書管理系統"
    • 增加一個

      ContentControl

      用來顯示頁面内容.
      • s:View.Model

        是Stylet提供的附加屬性, 用來為View綁定Model
      • ActiveItem

        Conductor<T>

        的一個屬性, 就是該Conductor的目前的頁面. 因為

        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

,激活新的頁面并關閉舊的. 我們使用該方法即可實作頁面的切換.

再次啟動程式, 确認首頁已經能正常顯示了:

【WPF on .NET Core 3.0】 Stylet示範項目 - 簡易圖書管理系統(3) - 使用Conductor切換頁面

顯示圖書頁面

  1. Page檔案夾中建立一個名為"Books"的檔案夾, 并建立一個C#類:

    IndexViewModel

    IndexView

    , 用來顯示圖書清單頁面:
    【WPF on .NET Core 3.0】 Stylet示範項目 - 簡易圖書管理系統(3) - 使用Conductor切換頁面
    要點如下:
    • IndexViewModel

      Screen

    • IndexView

      中增加一個

      TextBlock

      用來(暫時)辨別這是圖書頁面:

      <TextBlock Text="IndexView"/>

  2. 同樣, 在

    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~