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美麗的面紗.

  1. ShellViewModel.cs中增加一個Name屬性
  2. 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的綁定.

  1. ShellViewModel.cs中增加一個SayHello方法
  2. 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,里面有很多值得學習和參考的東西.

最后,祝大家工作生活愉快!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM