一、组件
ObservableObject
ObservableObject实现了INotifyPropertyChanged和INotifyPropertyChanging,并触发PropertyChanged和PropertyChanging事件
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 }
标签:Task,Mvvm,get,ObservableObject,Toolkit,Community,value,AsyncRelayCommand,public From: https://www.cnblogs.com/davisdabing/p/18191577