前言
官方文档
https://docs.microsoft.com/zh-cn/dotnet/communitytoolkit/mvvm/
安装
在解决方案资源管理器中,右键单击项目,然后选择“管理NuGet包”。 搜索 Microsoft.Toolkit.Mvvm 并安装它。
1
| Install-Package Microsoft.Toolkit.Mvvm -Version 7.1.2
|
添加 using 指令以使用新 API:
1
| using Microsoft.Toolkit.Mvvm;
|
这个包主要提供了如下的
- Microsoft.Toolkit.Mvvm.ComponentModel
- Microsoft.Toolkit.Mvvm.DependencyInjection
- Microsoft.Toolkit.Mvvm.Input
- Microsoft.Toolkit.Mvvm.Messaging
- Microsoft.Toolkit.Mvvm.Messaging.Messages
可观察对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class UserVM : ObservableObject { private string name;
public string Name { get => name; set => SetProperty(ref name, value); }
private int age;
public int Age { get => age; set => SetProperty(ref age, value); } }
|
页面的类中添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public partial class MainWindow : Window { private UserVM userVM = new UserVM();
public MainWindow() { InitializeComponent(); DataContext = userVM; Task.Run(() => { while (true) { userVM.Age += 1; Thread.Sleep(1000); } }); } }
|
页面中
1 2 3 4 5
| <Grid> <StackPanel> <TextBlock FontSize="30" Text="{Binding Age}" /> </StackPanel> </Grid>
|
我们就可以看到数字就会一直递增了。
命令
页面中我们添加命令
1 2 3 4 5 6
| <StackPanel Height="40" Orientation="Horizontal"> <TextBlock FontSize="30" Text="{Binding Name}" /> <TextBlock FontSize="30" Text="{Binding Age}" />
<Button Command="{Binding IncrementAgeCommand}" Content="年龄递增" /> </StackPanel>
|
对应的ViewModel中添加命令及响应的事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class UserVM : ObservableObject { private string name;
public string Name { get => name; set => SetProperty(ref name, value); }
private int age;
public int Age { get => age; set => SetProperty(ref age, value); }
public ICommand IncrementAgeCommand { get; } public UserVM() { IncrementAgeCommand = new RelayCommand(IncrementAge); } private void IncrementAge() => Age++; }
|
这样只要我们点击按钮,年龄就会递增1。
消息机制
注册与发送
添加传递消息的类
1 2 3 4 5 6 7 8 9 10 11 12
| public class ZMessage { public int Code { get; set; }
public string Message { get; set; }
public ZMessage(int code, string msg) { Code = code; Message = msg; } }
|
消息接收与发送
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public MainWindow() { InitializeComponent(); initMessage(); }
private void initMessage() { WeakReferenceMessenger.Default.Register<ZMessage>( this, (r, m) => { Console.WriteLine("接收到信息:" + m.Message); } );
WeakReferenceMessenger.Default.Send(new ZMessage(100, "Hello")); }
|
可接收消息的类
当然我们也可以让我们的ViewModel接收消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class UserVM : ObservableRecipient, IRecipient<ZMessage> { private string name;
public string Name { get => name; set => SetProperty(ref name, value); }
private int age;
public int Age { get => age; set => SetProperty(ref age, value); }
public UserVM() { IsActive = true; }
public void Receive(ZMessage message) { Name = message.Message; Age = message.Code; } }
|
这里一定要注意
我们还是在页面的类中发送消息
1
| WeakReferenceMessenger.Default.Send(new ZMessage(18, "XiaoMing"));
|
页面也稍做修改
1 2 3 4
| <StackPanel Orientation="Horizontal"> <TextBlock FontSize="30" Text="{Binding Name}" /> <TextBlock FontSize="30" Text="{Binding Age}" /> </StackPanel>
|
我们会发现页面上已经变更为我们发送消息的数据了。
控制反转(IOC)
添加依赖库Microsoft.Extensions.DependencyInjection
1
| Install-Package Microsoft.Extensions.DependencyInjection -Version 6.0.0
|
创建我们要自动注入的类
加入如下是我们用户相关的服务
1 2 3 4
| public interface IUserService { string getUserName(); }
|
和
1 2 3 4 5 6 7
| public class UserService : IUserService { public string getUserName() { return "XiaoMing"; } }
|
添加注入的控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public partial class App : Application { public App() { Services = ConfigureServices();
this.InitializeComponent(); }
public new static App Current => (App)Application.Current;
public IServiceProvider Services { get; }
private static IServiceProvider ConfigureServices() { var services = new ServiceCollection();
services.AddSingleton<IUserService, UserService>();
services.AddTransient<UserVM>();
return services.BuildServiceProvider(); } }
|
其中
- AddSingleton 单一实例服务
- AddScoped 范围内的服务
- AddTransient 暂时性服务
权重:
AddSingleton→AddTransient→AddScoped
生命周期:
注意:
由于AddScoped对象是在请求的时候创建的
所以不能在AddSingleton对象中使用
甚至也不能在AddTransient对象中使用
使用
1 2
| private UserVM userVM = (UserVM)App.Current.Services.GetService(typeof(UserVM)); private IUserService userService = (IUserService)App.Current.Services.GetService(typeof(IUserService));
|
这样是不是感觉还麻烦了
但是如果我们的ViewModel是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class UserVM : ObservableObject { private string name;
public string Name { get => name; set => SetProperty(ref name, value); }
private int age;
public int Age { get => age; set => SetProperty(ref age, value); }
public ICommand IncrementAgeCommand { get; }
public IUserService userService { get; }
public UserVM(IUserService _userService) { userService = _userService; IncrementAgeCommand = new RelayCommand(IncrementAge); }
private void IncrementAge() => Age++; }
|
这里的IUserService的实例并没有传入但是就可以用了,因为IOC框架已经自动注入了。