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,里面有很多值得學習和參考的東西.
最后,祝大家工作生活愉快!