天天看点

【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~