Community Mvvm Toolkit常用组件的基本使用(第一版)

一、组件

ObservableObject

ObservableObject实现了INotifyPropertyChangedINotifyPropertyChanging,并触发PropertyChangedPropertyChanging事件

 1 public class User : ObservableObject
 2 {
 3     private string name;
 4 
 5     public string Name
 6     {
 7         get => name;
 8         set => SetProperty(ref name, value);
 9     }
10 }

在这段示例代码中,如果 name 和 value 的值不同,首先触发 PropertyChanging 事件,然后触发 PropertyChanged

RelayCommand

RelayCommand 和 RelayCommand<T> 实现了 ICommand 接口,INotifyPropertyChanged  ICommand 是 MVVM 模式的基础。下面的代码使用 ObservableObject 和 RelayCommand 展示一个基本的 ViewModel:

 1 public class MyViewModel : ObservableObject
 2 {
 3     public MyViewModel()
 4     {
 5         IncrementCounterCommand = new RelayCommand(IncrementCounter);
 6     }
 7 
 8     private int counter;
 9 
10     public int Counter
11     {
12         get => counter;
13         private set => SetProperty(ref counter, value);
14     }
15 
16     public ICommand IncrementCounterCommand { get; }
17 
18     private void IncrementCounter() => Counter++;
19 }
 1 <Page
 2     x:Class="MyApp.Views.MyPage"
 3     xmlns:viewModels="using:MyApp.ViewModels">
 4     <Page.DataContext>
 5         <viewModels:MyViewModel x:Name="ViewModel"/>
 6     </Page.DataContext>
 7 
 8     <StackPanel Spacing="8">
 9         <TextBlock Text="{x:Bind ViewModel.Counter, Mode=OneWay}"/>
10         <Button
11             Content="Click me!"
12             Command="{x:Bind ViewModel.IncrementCounterCommand}"/>
13     </StackPanel>
14 </Page>

在这段示例里 IncrementCounterCommand 包装了 IncrementCounter 函数提供给 Button 绑定。IncrementCounter 函数更改 Counter 的值并通过 PropertyChanged 事件通知绑定的 TextBlock。

AsyncRelayCommand

AsyncRelayCommand 和 AsyncRelayCommand<T> 也实现了 ICommand,不过它们支持异步操作,提供的 ExecutionTask 和 IsRunning 两个属性对监视任务运行状态十分有用。

 

直接在Task中处理结果

界面布局:

2  <Label Content="{Binding GetTextCommand.ExecutionTask.Status}" HorizontalAlignment="Left"></Label>
3  <Label HorizontalAlignment="Left" Content="{Binding TextResult}"/>
4  <Button HorizontalAlignment="Left" VerticalAlignment="Top" Width="88" Content="开始任务" Command="{Binding GetTextCommand}"></Button>

ViewModel:

AsyncRelayCommand的构造函数需要传入一个返回Task类型的函数或委托。我这里定义了一个GetText函数,在函数里模拟等待了5秒(正常使用时,这个等待可以是任意一个耗时操作。)

 1 public class AsyncRelayCommandPageViewModel : ObservableObject
 2     {
 3         private string textResult;
 4         public string TextResult { get => textResult; set => SetProperty(ref textResult, value); }
 5 
 6         public IAsyncRelayCommand GetTextCommand { get; set; }
 7 
 8 
 9         public AsyncRelayCommandPageViewModel()
10         {
11             GetTextCommand = new AsyncRelayCommand(GetText);
12         }
13 
14         public async Task GetText()
15         {
16             await Task.Delay(3000); //模拟耗时操作
17             TextResult =  "Hello world!";
18         }
19     }

直接绑定到AsyncRelayCommand的ExecutionTask,然后用一个Converter来转换值

界面布局:

1  <Label Content="{Binding GetTextCommand2.ExecutionTask.Status}" HorizontalAlignment="Left"></Label>
2  <Label HorizontalAlignment="Left" Content="{Binding GetTextCommand2.ExecutionTask,Converter={StaticResource TaskResultConverter}}"/>
3  <Button HorizontalAlignment="Left" VerticalAlignment="Top" Width="88" Content="开始任务" Command="{Binding GetTextCommand2}"></Button>

ViewModel:

通过ExecutionTask属性,可以获取到GetTextCommand2最后执行的Task。

然后再通过一个CommunityToolkit.Common包中的Task.GetResultOrDefault()扩展函数,可以获取ExecutionTask的任务返回结果。

 1 public class AsyncRelayCommandPageViewModel : ObservableObject
 2     {
 3         public IAsyncRelayCommand GetTextCommand2 { get; set; }
 4 
 5 
 6         public AsyncRelayCommandPageViewModel()
 7         {
 8 
 9             GetTextCommand2 = new AsyncRelayCommand(GetText2);
10 
11         }
12 
13 
14         public async Task<string> GetText2()
15         {
16             await Task.Delay(3000); //模拟耗时操作
17             return "Hello world!";
18         }
19 }

Converter:

 1 using CommunityToolkit.Common;
 2 using System;
 3 using System.Globalization;
 4 using System.Threading.Tasks;
 5 using System.Windows.Data;
 6 
 7 namespace CommunityToolkit.Mvvm.WpfDemo.Converters
 8 {
 9     public class TaskResultConverter : IValueConverter
10     {
11 
12         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
13         {
14             if (value is Task task)
15             {
16                 return task.GetResultOrDefault();
17             }
18 
19             return null;
20         }
21 
22         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
23         {
24             throw new NotImplementedException();
25         }
26     }
27 }

 

 

posted on 2024-05-16 14:42  赵书记  阅读(1116)  评论(0)    收藏  举报