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


     

    本系列文章导航
    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 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}";
    }
    <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可以区分具体哪个属性

    ///
    /// 所有属性改变
    ///
    ///
    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 val ) =>
    //{
    // Title = $"hello(改):{val}";
    //} );
    }
    [RelayCommand]
    void ButtonClickPar ( double val )
    {
    Title = $"hello(改):{val}";
    }
    //public RelayCommand 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 ) );
    }
    ///
    /// 所有属性改变
    ///
    ///
    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 (代码地址)

     

  • 相关阅读:
    SaaSBase:什么是小裂变SCRM?
    idea安装与配置(2019版本)
    C语言天花板——指针(进阶1)
    连Producer端的主线程模块运行原理都不清楚,就敢说自己精通Kafka?
    MapReduce详细流程
    接口测试CURL复制以及postman的Code功能
    Springboot 启动Bean如何被加载
    “鼓浪屿元宇宙”,能否成为中国文旅产业的“升级样本”
    不可靠不重传的假 TCP
    重命名conda虚拟环境后jupyter无法启动的问题
  • 原文地址:https://www.cnblogs.com/aierong/p/17305990.html