前两章中, 我们已经实现了这个图书管理系统的登录窗口, 并实施了完善的单元测试. 该是时候回过头来关注我们的主窗口了.

一个功能丰富的系统一般会有多个页面, 我们图书管理系统虽然是"简易"的, 但是同样也有多个页面. 所以这一章中, 我们来学习如何使用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~

【WPF on .NET Core 3.0】 Stylet演示项目 - 简易图书管理系统(3) - 使用Conductor切换页面的更多相关文章

  1. 【WPF on .NET Core 3.0】 Stylet演示项目 - 简易图书管理系统(1)

    .NET Core 3.0已经发布了,除了一大堆令人激动的功能以外,也增加了对WPF的正式支持, 那么WPF在.NET Core 3.0下的开发体验如何呢? 本文利用了Stylet框架开发.NET C ...

  2. 【WPF on .NET Core 3.0】 Stylet演示项目 - 简易图书管理系统(2) - 单元测试

    上一章中我们完成了一个简单的登录功能, 这一章主要演示如何对Stylet工程中的ViewModel进行单元测试. 回忆一下我们的登录逻辑,主要有以下4点: 当"用户名"或" ...

  3. 【WPF on .NET Core 3.0】 Stylet演示项目 - 简易图书管理系统(4) - 图书列表界面

    在前三章中我们完成了登录窗口, 并掌握了使用Conductor来切换窗口, 但这些其实都是在为我们的系统打基础. 而本章中我们就要开始开发系统的核心功能, 即图书管理功能了. 通过本章, 我们会接触到 ...

  4. Windows Forms和WPF在Net Core 3.0框架下并不会支持跨平台

    Windows Forms和WPF在Net Core 3.0框架下并不会支持跨平台 微软将WinForms和WPF带到.NET Core 3.0这一事实,相信大家都有所了解,这是否意味着它在Linux ...

  5. .Net Core .Net Core V1.0 创建MVC项目

    .Net Core V1.0 创建MVC项目 创建MVC项目有两种方式: 一.创建Web项目:(有太多没用的东西要去删太麻烦) 2.项目目录结构: 此种方法要注意的是,会创建好多个json文件,下面就 ...

  6. 用VSCode开发一个asp.net core 2.0+angular 5项目(4): Angular5全局错误处理

    第一部分: http://www.cnblogs.com/cgzl/p/8478993.html 第二部分: http://www.cnblogs.com/cgzl/p/8481825.html 第三 ...

  7. .Net Core 3.0开源可视化设计CMS内容管理系统建站系统

    简介 ZKEACMS,又名纸壳CMS,是可视化编辑设计的内容管理系统.基于.Net Core开发可跨平台运行,并拥有卓越的性能. 纸壳CMS基于插件式设计,功能丰富,易于扩展,可快速创建网站. 布局设 ...

  8. .Net大局观(2).NET Core 2.0 特性介绍和使用指南

    .NET Core 2.0发布日期:2017年8月14日 前言 这一篇会比较长,系统地介绍了.NET Core 2.0及生态,现状及未来计划,可以作为一门技术的概述来读,也可以作为学习路径.提纲来用. ...

  9. .Net Core 2.0 生态(2).NET Core 2.0 特性介绍和使用指南

    .NET Core 2.0发布日期:2017年8月14日 前言 这一篇会比较长,介绍了.NET Core 2.0新特性.工具支持及系统生态,现状及未来计划,可以作为一门技术的概述来读,也可以作为学习路 ...

随机推荐

  1. Http协议Content-Length详解

    前言 http协议是互联网中最重要的协议之一,虽然看上去很简单,但是实际中经常遇到问题,我们就已经遇到好几次了.有长连接相关的,有报文解析相关的.对http协议不能一知半解,必须透彻理解才行.本文通过 ...

  2. Python 爬虫从入门到进阶之路(十)

    之前的文章我们介绍了一下 Python 中正则表达式和 re 模块来做一个案例,爬取<糗事百科>的糗事并存储到本地.本章我们来看一下另一种爬取数据的方式 XPath. 我们在前面爬取< ...

  3. MFC下使用Mysql

    MFC工程需要使用Mysql数据库中遇到的问题记录下. 1.首先去官网下载下Mysql安装包,安装下Mysql. 我在这边下载的是mysql-installer-community-5.7.16.0. ...

  4. 爬虫破解知乎登入(不使用Selenium模块)

    一.分析 知乎完成登入的步骤 首先获得cookies(如果不获得后面验证码无法获得) 获得验证码 提交登入相关内容 前两步简单稍微细心寻找规律即可 其中最难的是第三步应该他前端进行了js加密 这里没什 ...

  5. unittest中的方法调用时报错ValueError: no such test method in <class 'mytestcase.MyTestCase'>: runTest

    调用unittest中的方法时报错: ValueError: no such test method in <class 'mytestcase.MyTestCase'>: runTest ...

  6. Numpy中的三个常用正态分布相关的函数,randn,standard_normal, normal的区别

    这三个函数都可以返回随机正态分布(高斯Gaussian 分布)的数组,都可以从numpy.random中导出 先看三个函数的参数方式: randn: randn(d0, d1, ..., dn), 返 ...

  7. windows服务隐藏后门之克隆帐号

    windows服务隐藏后门之克隆帐号 1.CMD命令行下,建立了一个用户名为“test$”,密码为“abc123!”的简单隐藏账户,并且把该隐藏账户提升为了管理员权限. PS:CMD命令行使用&quo ...

  8. shark恒破解笔记6-BC++假自效验

    这小节介绍了查壳(peid) 查软件编写语言(die)以及用esp定律脱aspack壳,最后是破解bc++的自校验部分 目标: 首先查看软件 peid查壳 有壳 ,但是不知道是什么语言写的,这里使用D ...

  9. 第三方应用 flashfxp,filezilla提权

    filezilla 提权 filezilla 开源的ftp服务器 默认监听14147端口 默认安装目录下有个敏感文件 filezillaserver.xml(包含用户信息) filezillaserv ...

  10. python深拷贝与浅拷贝的区别

    可变对象:一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值 不可变对象:一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么它指向的地址就改变了,相当于你把这个对象 ...