CommunityToolkit.Mvvm8.1 viewmodel源生成器写法(3)

  • CommunityToolkit.Mvvm8.1 viewmodel源生成器写法(3)已关闭评论
  • 123 次浏览
  • A+
所属分类:.NET技术
摘要

  CommunityToolkit.Mvvm8.1最令人惊喜的是它提供的源生成器功能,它极大简化我们的mvvm代码
我们通过标记一个属性就可以实现某个功能,这个很方便快捷,推荐

 

本系列文章导航
  1. https://www.cnblogs.com/aierong/p/17300066.html
  2. https://github.com/aierong/WpfDemo (自我Demo地址)

希望提到的知识对您有所提示,同时欢迎交流和指正
作者:aierong
出处:https://www.cnblogs.com/aierong

 

说明

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;         }      } }

 

导航

https://github.com/aierong/WpfDemo/tree/main/WpfDemoNet6 (项目地址)

https://github.com/aierong/WpfDemo/blob/main/WpfDemoNet6/Demo/DataViewModel2.cs (代码地址)