什么是MVVM Toolkit
大家一说起WPF或者UWP能用的MVVM框架,肯定主流的推荐就是Prism和MVVMLight这两个,算是使用最广泛的,但是目前Prism已经不再支持UWP了,然后MVVMLight已经多年不更新了,那就玩完了?
不,官方社区套件(
Windows Community Toolkit
)挺身而出,带来了拯救版MVVM Toolkit这个MVVM框架
MVVM Toolkit
延续了MVVMLight
的风格,是一个轻量级的组件,而且它基于.NET Standard 2.0
,可用于UWP
, WinForms
, WPF
, Xamarin
, Uno
等多个平台。
相比它的前身 MVVMLight,它有以下特点:
- 更高:版本号更高,一出手就是7.0。
- 更快:速度更快,MVVM Toolkit从一开始就以高性能为实现目标。
- 更强:后台更强,MVVM Toolkit的全程是'Microsoft.Toolkit.Mvvm',根正苗红。
安装MVVM Toolkit
dotnet add package Microsoft.Toolkit.Mvvm
官方指导文档
https://docs.microsoft.com/zh-cn/windows/communitytoolkit/mvvm/introduction
using Microsoft.Toolkit.Mvvm;
官方指导示例
项目源码仓库
开发探索指引
ObservableObject
public class User : ObservableObject
{
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
}
RelayCommand
public class MyViewModel : ObservableObject
{
public MyViewModel()
{
IncrementCounterCommand = new RelayCommand(IncrementCounter);
}
private int counter;
public int Counter
{
get => counter;
private set => SetProperty(ref counter, value);
}
public ICommand IncrementCounterCommand { get; }
private void IncrementCounter() => Counter++;
}
<Page
x:Class="MyApp.Views.MyPage"
xmlns:viewModels="using:MyApp.ViewModels">
<Page.DataContext>
<viewModels:MyViewModel x:Name="ViewModel"/>
</Page.DataContext>
<StackPanel Spacing="8">
<TextBlock Text="{x:Bind ViewModel.Counter, Mode=OneWay}"/>
<Button
Content="Click me!"
Command="{x:Bind ViewModel.IncrementCounterCommand}"/>
</StackPanel>
</Page>
AsyncRelayCommand
public MyViewModel()
{
DownloadTextCommand = new AsyncRelayCommand(DownloadTextAsync);
}
public IAsyncRelayCommand DownloadTextCommand { get; }
private async Task<string> DownloadTextAsync()
{
await Task.Delay(3000); // Simulate a web request
return "Hello world!";
}
<Page.Resources>
<converters:TaskResultConverter x:Key="TaskResultConverter"/>
</Page.Resources>
<StackPanel Spacing="8">
<TextBlock>
<Run Text="Task status:"/>
<Run Text="{x:Bind ViewModel.DownloadTextCommand.ExecutionTask.Status, Mode=OneWay}"/>
<LineBreak/>
<Run Text="Result:"/>
<Run Text="{x:Bind ViewModel.DownloadTextCommand.ExecutionTask, Converter={StaticResource TaskResultConverter}, Mode=OneWay}"/>
</TextBlock>
<Button
Content="Click me!"
Command="{x:Bind ViewModel.DownloadTextCommand}"/>
<muxc:ProgressRing
HorizontalAlignment="Left"
IsActive="{x:Bind ViewModel.DownloadTextCommand.IsRunning, Mode=OneWay}"/>
</StackPanel>
Messenger
// Create a message
public class LoggedInUserChangedMessage : ValueChangedMessage<User>
{
public LoggedInUserChangedMessage(User user) : base(user)
{
}
}
// Register a message in some module
WeakReferenceMessenger.Default.Register<LoggedInUserChangedMessage>(this, (r, m) =>
{
// Handle the message here, with r being the recipient and m being the
// input messenger. Using the recipient passed as input makes it so that
// the lambda expression doesn't capture "this", improving performance.
});
// Send a message from some other module
WeakReferenceMessenger.Default.Send(new LoggedInUserChangedMessage(user));
ObservableRecipient
public class MyViewModel : ObservableRecipient, IRecipient<LoggedInUserRequestMessage>
{
public void Receive(LoggedInUserRequestMessage message)
{
// Handle the message here
}
}
参考
- https://github.com/PrismLibrary/Prism/issues/2025
- https://github.com/lbugnion/mvvmlight
- [WPF] 使用 MVVM Toolkit 构建 MVVM 程序