- A+
说明
CommunityToolkit.Mvvm8.1最令人惊喜的是它提供的源生成器功能,它极大简化我们的mvvm代码
我们通过标记一个属性就可以实现某个功能,这个很方便快捷,推荐
常用标记总结
1.继承ObservableObject 并且类标记是分部类partial
2.私有变量标记属性 [ObservableProperty]
3.NotifyCanExecuteChangedFor 通知依赖命令
NotifyPropertyChangedFor 通知依赖属性
4.RelayCommand 定义命令
5.OnPropertyChanged 手动通知属性更新
6.ButtonClickCommand.NotifyCanExecuteChanged() 手动通知命令更新
7.OnLastNameChanging OnLastNameChanged 某个属性改变
8.OnPropertyChanged 所有属性改变
定义viewmodel
定义vm时,请使用分部类,并且继承ObservableObject
public partial class DataViewModel2 : ObservableObject { }
ObservableProperty标记属性
定义属性如此简单:一个[ObservableProperty]标记搞定
/* [ObservableProperty]标记后,会自动生成属性(大写命名),例如:下面会自动生成Title 注意:这个私有变量命名:必须是小写开头,或者下划线,或者m_ */ [ObservableProperty] private string title = "hello"; //public string Title //{ // get // { // return title; // } // set // { // //title = value; // //PropertyChanged?.Invoke( this , new PropertyChangedEventArgs( "Name" ) ); // //SetProperty 相当与设置值,并且PropertyChanged通知调用 // SetProperty( ref title , value ); // } //}
NotifyPropertyChangedFor通知依赖属性
[NotifyPropertyChangedFor( nameof( Caption ) )]标识:在LastName改变后,去通知Caption
public string Caption { get { return string.Format( "Title:{0}-{1}" , Title , LastName ); } } [ObservableProperty] [NotifyPropertyChangedFor( nameof( Caption ) )] private string lastName = "abc";
NotifyCanExecuteChangedFor通知依赖命令
在属性IsEnabled改变后,通知命令:ButtonClickCommand
/* [NotifyCanExecuteChangedFor( nameof( ButtonClickCommand ) )] NotifyCanExecuteChangedFor是通知依赖命令(触发命令),相当于set中ButtonClickCommand.NotifyCanExecuteChanged(); */ [ObservableProperty] [NotifyCanExecuteChangedFor( nameof( ButtonClickCommand ) )] private bool isEnabled = false; //public bool IsEnabled //{ // get => isEnabled; // set // { // SetProperty( ref isEnabled , value ); // //通知命令 已经改变 // ButtonClickCommand.NotifyCanExecuteChanged(); // } //} //partial void OnIsEnabledChanged ( bool value ) //{ // //如果上面的[NotifyCanExecuteChangedFor( nameof( ButtonClickCommand ) )]不写,可以这里手动通知更新 // //ButtonClickCommand.NotifyCanExecuteChanged(); //}
命令
RelayCommand标识定义一个命令,如此简单
/* RelayCommand是定义命令,自动生成的命令名是方法名+Command,并且初始化 例如:下面的会自动生成ButtonClickCommand CanExecute是指定一个判断方法,判断是否可用 */ [RelayCommand( CanExecute = nameof( CanButton ) )] void ButtonClick () { //点击按钮,修改标题 Title = "hello(改)"; } bool CanButton () { return IsEnabled; } //public RelayCommand ButtonClickCommand //{ // get; //} [RelayCommand] void ButtonClickPar ( double val ) { Title = $"hello(改):{val}"; } //public RelayCommand<double> ButtonClickParCommand //{ // get; //}
异步命令
把方法标识为async,即可定义为异步命令,它带有一个IsRunning属性,可以在view中做进度条判断
[RelayCommand] async Task AsyncButtonClick () { await Task.Delay( 4800 ); Title = "hello(Task改)"; } [RelayCommand] async Task AsyncButtonParClick ( double val ) { await Task.Delay( 4800 ); Title = $"hello(Task改):{val}"; }
<!-- 特别说明:异步命令会自动控制控件的可见性,并且提供一个IsRunning属性可以判断异步是否完成 --> <Button Width="100" Height="30" Command="{Binding AsyncButtonClickCommand}" Content="异步" /> <TextBlock HorizontalAlignment="Center" FontSize="20" FontStyle="Italic" FontWeight="Bold" Foreground="Green" Text="loading......" Visibility="{Binding AsyncButtonClickCommand.IsRunning, Converter={StaticResource myboolconvert}}" />
某个属性改变
On+属性Changing On+属性Changed,可以记录某个属性值变化事件
/* 还可以实现2个方法:OnLastNameChanging OnLastNameChanged (注意2个方法只可以实现其中一个,或者都不实现(不能同时2个)) */ //partial void OnLastNameChanging ( string value ) //{ // Debug.WriteLine( value ); //} partial void OnLastNameChanged ( string value ) { // 可以做一些其它事情 例如:属性改变后,消息通知某某某 Debug.WriteLine( value ); //说明:如果上面[NotifyPropertyChangedFor( nameof( Caption ) )]不写,可以这里手动通知属性更新 //OnPropertyChanged( nameof( Caption ) ); }
所有属性改变
所有属性改变后都会调用这个事件,参数PropertyName可以区分具体哪个属性
/// <summary> /// 所有属性改变 /// </summary> /// <param name="e"></param> protected override void OnPropertyChanged ( PropertyChangedEventArgs e ) { base.OnPropertyChanged( e ); // 可以获取到是哪个属性改变了 var _proname = e.PropertyName; }
完整代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; /* 这里演示自动生成属性和命令 1.继承ObservableObject 并且类标记是分部类partial 2.私有变量标记属性 [ObservableProperty] 3.NotifyCanExecuteChangedFor 通知依赖命令 NotifyPropertyChangedFor 通知依赖属性 4.RelayCommand 定义命令 5.OnPropertyChanged 手动通知属性更新 6.ButtonClickCommand.NotifyCanExecuteChanged() 手动通知命令更新 7.OnLastNameChanging OnLastNameChanged 某个属性改变 8.OnPropertyChanged 所有属性改变 */ namespace WpfDemoNet6.Demo { public partial class DataViewModel2 : ObservableObject { /* [ObservableProperty]标记后,会自动生成属性(大写命名),例如:下面会自动生成Title 注意:这个私有变量命名:必须是小写开头,或者下划线,或者m_ */ /* NotifyPropertyChangedFor 通知依赖属性Caption */ [ObservableProperty] [NotifyPropertyChangedFor( nameof( Caption ) )] private string title = "hello"; //public string Title //{ // get // { // return title; // } // set // { // //title = value; // //PropertyChanged?.Invoke( this , new PropertyChangedEventArgs( "Name" ) ); // //SetProperty 相当与设置值,并且PropertyChanged通知调用 // SetProperty( ref title , value ); // } //} /* [NotifyCanExecuteChangedFor( nameof( ButtonClickCommand ) )] NotifyCanExecuteChangedFor是通知依赖命令(触发命令),相当于set中ButtonClickCommand.NotifyCanExecuteChanged(); */ [ObservableProperty] [NotifyCanExecuteChangedFor( nameof( ButtonClickCommand ) )] private bool isEnabled = false; //public bool IsEnabled //{ // get => isEnabled; // set // { // SetProperty( ref isEnabled , value ); // //通知命令 已经改变 // ButtonClickCommand.NotifyCanExecuteChanged(); // } //} //partial void OnIsEnabledChanged ( bool value ) //{ // //如果上面的[NotifyCanExecuteChangedFor( nameof( ButtonClickCommand ) )]不写,可以这里手动通知更新 // //ButtonClickCommand.NotifyCanExecuteChanged(); //} /* RelayCommand是定义命令,自动生成的命令名是方法名+Command,并且初始化 例如:下面的会自动生成ButtonClickCommand CanExecute是指定一个判断方法,判断是否可用 */ [RelayCommand( CanExecute = nameof( CanButton ) )] void ButtonClick () { //点击按钮,修改标题 Title = "hello(改)"; } bool CanButton () { return IsEnabled; } //public RelayCommand ButtonClickCommand //{ // get; //} public DataViewModel2 () { //RelayCommand的第一个参数是命令调用语句 // 第2个参数(可选)是否允许使用 //ButtonClickCommand = new RelayCommand( () => //{ // //点击按钮,修改标题 // Title = "hello(改)"; //} , () => //{ // return IsEnabled; //} ); //ButtonClickParCommand = new RelayCommand<double>( ( double val ) => //{ // Title = $"hello(改):{val}"; //} ); } [RelayCommand] void ButtonClickPar ( double val ) { Title = $"hello(改):{val}"; } //public RelayCommand<double> ButtonClickParCommand //{ // get; //} public string Caption { get { return string.Format( "Title:{0}-{1}" , Title , LastName ); } } [ObservableProperty] [NotifyPropertyChangedFor( nameof( Caption ) )] private string lastName = "abc"; /* 还可以实现2个方法:OnLastNameChanging OnLastNameChanged (注意2个方法只可以实现其中一个,或者都不实现(不能同时2个)) */ //partial void OnLastNameChanging ( string value ) //{ // Debug.WriteLine( value ); //} partial void OnLastNameChanged ( string value ) { // 可以做一些其它事情 例如:属性改变后,消息通知某某某 Debug.WriteLine( value ); //说明:如果上面[NotifyPropertyChangedFor( nameof( Caption ) )]不写,可以这里手动通知属性更新 //OnPropertyChanged( nameof( Caption ) ); } /// <summary> /// 所有属性改变 /// </summary> /// <param name="e"></param> protected override void OnPropertyChanged ( PropertyChangedEventArgs e ) { base.OnPropertyChanged( e ); // 可以获取到是哪个属性改变了 var _proname = e.PropertyName; } } }