【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, 用來顯示我們系統的首頁.

  • 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
      • ActiveItemConductor<T>的一個屬性, 就是該Conductor的當前的頁面. 因為ShellViewModel繼承了Conductor<T>, 所以在ShellView中可以綁定該屬性.

顯示首頁

如果你現在啟動程序, 會發現程序可以正常啟動, 但是Shell中不會顯示任何內容. 這是因為我們未給ShellViewModel這個Conductor設置ActiveItem.

ShellViewModelOnViewLoaded方法的開始位置, 增加以下代碼, 用來在程序啟動時就顯示首頁.

    protected override void OnViewLoaded()
    {
        // 顯示首頁
        var homeViewModel = _container.Get<HomeViewModel>();
        ActivateItem(homeViewModel);

        // 顯示登錄窗口
        ...
    }

ActivateItem方法是Condocutor<T>中提供的方法.用一個新的ViewModel實例替換當前的ActiveItem,激活新的頁面並關閉舊的. 我們使用該方法即可實現頁面的切換.

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

顯示圖書頁面

  1. Page文件夾中新建一個名為"Books"的文件夾, 並新建一個C#類: IndexViewModel和一個UserControl: IndexView, 用來顯示圖書列表頁面:

    要點如下:

    • IndexViewModel的基類設置為Screen
    • IndexView中增加一個TextBlock用來(暫時)標識這是圖書頁面: <TextBlock Text="IndexView"/>
  2. 同樣, 在ShellViewModelOnViewLoaded方法的末尾位置, 增加以下代碼, 用來在登錄成功后, 切換到圖書頁面:

    protected override void OnViewLoaded()
    {
        // 顯示首頁
        var homeViewModel = _container.Get<HomeViewModel>();
        ActivateItem(homeViewModel);

        // 顯示登錄窗口
        ...

        // 顯示圖書
        var indexViewModel = _container.Get<IndexViewModel>();
        ActivateItem(indexViewModel);
    }

再次使用ActivateItem方法, 將圖書的ViewModel切換進來. 再次啟動程序, 確認當登錄成功后, 主窗口的頁面會切換到圖書頁面.(目前只顯示一個IndeView, 我們會在下一章完善該頁面的功能)

本篇到此為止, 希望朋友們能多多留言, 鼓勵我能繼承寫下去. 源碼托管在GITHUB上.

Happy Coding~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM