ViewModel从未如此清爽 - 轻量级WPF MVVM框架Stylet
Stylet是我最近发现的一个WPF MVVM框架, 在博客园上搜了一下, 相关的文章基本没有, 所以写了这个入门的文章推荐给大家.
Stylet是受Caliburn Micro项目的启发, 所以借鉴了其中的很多概念, 同时精简了一些部分, 如只支持MVVM, WPF和.NET 4.5(Silverlight和Xamarin不受支持), 所以Style本身很小巧, DLL才140KB左右.
虽然身材小,但相比知名的MVVM框架, 如MVVM Light等功能却一点都不差,加上很完善的文档,高覆盖率的单元测试,我认为它是一个很有潜力的MVVM框架.
下面就通过一个类似Hello World的小例子, 给大家演示一下Stylet既简洁又强大的功能.
创建工程
创建一个标准的WPF工程, 命名为StyletStudy
安装Style.Start包
打开包管理器命令行, 执行以下命令:
Install-Package Stylet.Start
.
Stylet.Start
会自动添加Stylet的引用, 并生成Stylet项目基本的文件, 安装成功后, 项目结构如下所示:
此时,你就可以按F5启动项目, 看看你的第一个Stylet项目的样子吧.
绑定属性
当然,如果只是这样,那么根本没有展现Stylet的魅力, 下面我们加入一些小改动, 用来揭开Stylet美丽的面纱.
- 在
ShellViewModel.cs
中增加一个Name
属性 - 在
ShellView.xaml
中增加一个TextBox
, 绑定Name
Name
属性:
using Stylet;
namespace StyletStudy.Pages
{
public class ShellViewModel : Screen
{
public string Name { get; set; } = "waku"; // C#6的语法, 声明自动属性并赋值
}
}
TextBox
:
<Window x:Class="StyletStudy.Pages.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StyletStudy.Pages"
mc:Ignorable="d"
Title="Stylet Start Project" Height="350" Width="525"
xmlns:s="https://github.com/canton7/Stylet"
d:DataContext="{d:DesignInstance local:ShellViewModel}">
<StackPanel>
<TextBox Text="{Binding Name}"></TextBox>
</StackPanel>
</Window>
也许你会注意到, 为TextBox
设置绑定时, Visual Studio是有智能提示的:
这是因为贴心的Stylet已经为你将设计时的DataContext设置为ShellViewModel
, 注意XAML的第10行:
d:DataContext="{d:DesignInstance local:ShellViewModel}">
再次启动, 可以看到属性的绑定已经成功了:
绑定命令
Stylet中对Command的实现方式深受Caliburn.Micro的影响,这也是Caliburn.Micro一大亮点,即通过命名约定实现Command的绑定.
- 在
ShellViewModel.cs
中增加一个SayHello
方法 - 在
ShellView.xaml
中增加一个Button
, 绑定SayHello
SayHello
方法:
public string Name { get; set; } = "waku";
public void SayHello() => Name = "Hello " + Name; // C#6的语法, 表达式方法
}
SayHello
只是简单的在Name
前加上"Hello ".
Button
:
<StackPanel>
<TextBox Text="{Binding Name}"></TextBox>
<Button Content="Say Hello" Command="{s:Action SayHello}"></Button>
</StackPanel>
注意Command="{s:Action SayHello}
的语法,s:Action
就是Stylet的魔法之一, 如此绑定后, 当点击SayHello
按钮后,会自动调用ViewModel中的SayHello
方法, 是不是很神奇?
启动程序,如果你在SayHello
中加入一个断点,当点击SayHello
按钮后,断点应该就被触发了:
但是,你会发现文本框中的内容并没有被加上"Hello ",为什么呢?
如果你是一个合格的WPF程序员,你应该发现了其中的问题: Name属性没有引发PropertyChanged
通知
实现PropertyChanged通知
MVVM框架一般通过继承一个实现了INotifyPropertyChanged
的基类, 然后在属性的set
方法中, 引发PropertyChanged
通知.
不同的MVVM框架,可能用一些辅助方法来简化这一过程, 如下面是MVVM Light实现Name
属性的方法:
private string _name;
public string Name
{
get { return _name; }
set
{
if (Set(ref _name, value))
{
}
}
}
Stylet也可以用类似的方法来引发PropertyChanged
, 但是如果只是那样我文章的标题就需要改名了:)
为了清爽的ViewModel, Stylet内置了对PropertyChanged.Fody的支持.
PropertyChanged.Fody
是一个非常神奇的包, 它会在编译时为你的属性注入IL代码, 来引发PropertyChanged
通知,是不是听上去就非常牛X?
当然PropertyChanged.Fody
不是Stylet专用的,你也可以在你自己的WPF项目中使用该包.
为Stylet启用PropertyChanged.Fody
只需要一条命令安装即可:
Install-Package PropertyChanged.Fody
安装后,代码无需任何修改,直接按F5运行.
再点击SayHello
按钮,看看是不是Hello了?
防护属性(Guard Properties)
我想当TextBox
为空时, 自动禁用SayHello
按钮, 这样的需求在开发中很常见.
Stylet为你考虑到了这一点,你只需要实现一个防护属性即可.
对于SayHello
方法, 实现一个CanSayHello
属性, 返回一个bool
型结果,标识SayHello
是否可被执行.代码如下:
public void SayHello() => Name = "Hello " + Name; // C#6的语法, 表达式方法
public bool CanSayHello => !string.IsNullOrEmpty(Name); // 同上
xaml中也需要为TextBox
的绑定做一些修改:
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<Button Content="Say Hello" Command="{s:Action SayHello}"></Button>
为绑定加上UpdateSourceTrigger=PropertyChanged
, 这样只要Name
有任何修改,会立即评估CanSayHello
属性.
再次启动项目,看看效果:
结语
至此,我们Stylet的入门演示项目就开发完了,
可以看到ViewModel中我们自己写的代码只有3行,就完成了属性绑定,命令绑定,防护属性功能. 是不是够清爽?
当然,Stylet还有很多令人激动的特性,解决了长久以来WPF开发中的痛点,如弹出窗体消息框(通过WindowManager), 表单验证(通过ValidatingModelBase),甚至Stylet中还内置了一个性能非常棒的IoC容器.
强烈建议感兴趣的朋友看看Stylet的WIKI,里面有很多值得学习和参考的东西.
最后,祝大家工作生活愉快!
ViewModel从未如此清爽 - 轻量级WPF MVVM框架Stylet的更多相关文章
- .NET Core 3 WPF MVVM框架 Prism系列之命令
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的命令的用法 一.创建DelegateCommand命令 我们在上一篇.NET Core 3 WPF MVVM框架 Prism系列之 ...
- .NET Core 3 WPF MVVM框架 Prism系列之对话框服务
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的对话框服务,这也是prism系列的最后一篇完结文章,下面是Prism系列文章的索引: .NET Core 3 WPF MVVM框 ...
- .NET Core 3 WPF MVVM框架 Prism系列之事件聚合器
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的使用事件聚合器实现模块间的通信 一.事件聚合器 在上一篇 .NET Core 3 WPF MVVM框架 Prism系列之模块化 ...
- .NET Core 3 WPF MVVM框架 Prism系列文章索引
.NET Core 3 WPF MVVM框架 Prism系列之数据绑定 .NET Core 3 WPF MVVM框架 Prism系列之命令 .NET Core 3 WPF MVVM框架 Prism系列 ...
- WPF MVVM框架(5)
前面几章节所讲到的内容, 基本上属于前端XAML的使用方法, 那么本章及后面的章节, 则会侧重于UI与业务分离如何分离 . UI与业务逻辑之间的互操作性,, 下面将介绍WPF中, 比较主流的MVVM框 ...
- .NET Core 3 WPF MVVM框架 Prism系列之导航系统
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism基于区域Region的导航系统 在讲解Prism导航系统之前,我们先来看看一个例子,我在之前的demo项目创建一个登录界面: 我们看 ...
- 轻量级前端MVVM框架avalon - 初步接触
迷你简单易用的MVVM框架 avalon的介绍http://rubylouvre.github.io/mvvm/ 按照作者的介绍,在HTML中添加绑定,在JS中用avalon.define定义View ...
- .NET Core 3 WPF MVVM框架 Prism系列之模块化
本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的应用程序的模块化 前言 我们都知道,为了构成一个低耦合,高内聚的应用程序,我们会分层,拿一个WPF程序来说,我们通过MVVM模式 ...
- 轻量级前端MVVM框架avalon - 执行流程2
接上一章 执行流程1 在这一大堆扫描绑定方法中应该会哪些实现? 首先我们看avalon能帮你做什么? 数据填充,比如表单的一些初始值,切换卡的各个面板的内容({{xxx}},{{xxx|html}}, ...
随机推荐
- lua 数据类型
lua 数据类型 8 种数据类型 类型 说明 nil 空类型 boolean 布尔类型 number 数值型, 浮点型 string 字符串 function 函数 userdata 用户自定义结构 ...
- JDK源码之PriorityQueue源码剖析
除特别注明外,本站所有文章均为原创,转载请注明地址 一.优先队列的应用 优先队列在程序开发中屡见不鲜,比如操作系统在进行进程调度时一种可行的算法是使用优先队列,当一个新的进程被fork()出来后,首先 ...
- DirectFB学习笔记二
本篇目的,画一个方框,在方框上画一串字符. 实现步骤:首先创建IDirectFB接口,通过它再创建要显示的表面surface,同时创建字体font,绘制字符必须要设置绘制的字体,否则绘制不成功.然后清 ...
- Js 网页版扫雷游戏代码实现
这个游戏是自己在大约一年前联系js熟练度时做的,用的都是基础的东西,最近比较忙没时间整理.直接发给大家,有兴趣的可以看一下.欢迎大家提出建议.如果你有什么新的想法也可以提出来,或者你并不擅长编程.你想 ...
- Akka(1):Actor - 靠消息驱动的运算器
Akka是由各种角色和功能的Actor组成的,工作的主要原理是把一项大的计算任务分割成小环节,再按各环节的要求构建相应功能的Actor,然后把各环节的运算托付给相应的Actor去独立完成.Akka是个 ...
- JavaScript中undefined 和not defined
首先呢,我们来介绍undefined,xx is not defined的区别 (创建一个html文件,在头部编写JavaScript代码) 我们先编写如下代码: <script type=&q ...
- luogu P1015 回文数
题目描述: 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制 ...
- ReactiveCocoa学习总结(2)
信号(signal)- RACSignal类 1. 一般表示将来有数据传递,只要有数据改变,信号内部接收到数据,就会马上发出数据. 2. 事件类型: next:发送数据到下一个管道 error:发送数 ...
- 学生成绩管理C语言版
[标题]学生成绩管理的设计与实现 [开发语言]C语言 [概要设计]使用结构体存储学生的学号.姓名和成绩信息,实现对学生成绩类的基本操作:增加.删除.查询.排序 [测试数据]按提示输入5组正确的正确的数 ...
- 关于listener监听器的一些记录
实现ServletContextListener后,需要实现2个方法,一个是contextInitialized,这个方法会在context被创建的时候执行,这个方法有一个参数为ServletCont ...