"Stylet" 是我最近發現的一個WPF MVVM框架, 在博客園上搜了一下, 相關的文章基本沒有, 所以寫了這個入門的文章推薦給大家. Stylet是受 "Caliburn Micro" 項目的啟發, 所以借鑒了其中的很多概念, 同時精簡了一些部分, 如只支持MVVM, WPF和.NET 4.5 ...
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,裡面有很多值得學習和參考的東西.
最後,祝大家工作生活愉快!