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

来源:https://www.cnblogs.com/aierong/archive/2023/04/11/17305990.html
-Advertisement-
Play Games

本系列文章導航 https://www.cnblogs.com/aierong/p/17300066.html https://github.com/aierong/WpfDemo (自我Demo地址) 希望提到的知識對您有所提示,同時歡迎交流和指正 作者:aierong出處:https://www ...


 

本系列文章導航
  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 (代碼地址)

 

我的系列文章
A.Sql Server2005 Transact-SQL 新兵器學習
B.MCAD學習
C.代碼閱讀總結
D.ASP.NET狀態管理
E.DB(資料庫)
F.WAP
G.WinForm
H.Flex

希望上面提到的知識對您有所提示,同時歡迎交流和指正
作者:aierong
出處:http://www.cnblogs.com/aierong
貼子以"現狀"提供且沒有任何擔保,同時也沒有授予任何權利!
本文版權歸作者所有,歡迎轉載!
原創技術文章和心得,轉載註明出處!這也是對原創者的尊重!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MongoDB索引優化 作者: 博學谷狂野架構師 GitHub:GitHub地址 (有我精心準備的130本電子書PDF) 只分享乾貨、不吹水,讓我們一起加油!😄 索引簡介 索引通常能夠極大的提高查詢的效率,如果沒有索引,MongoDB在讀取數據時必須掃描集合中的每個文件並選取那些符合查詢條件的記錄 ...
  • 面向對象封裝特點之一就是通過實現好的方法來訪問,限制對數據的不合理訪問,把對象狀態私有化,僅供類的內部進行操作 下方示例,Test方法的number屬性類實例的時候傳遞1,number是一個公開屬性,可以在外部任意修改、訪問,沒有對屬性進行進行約束 class Test: def __init__( ...
  • 當前主流編程語言的垃圾收集器基本上都是依靠可達性分析演算法來判定對象是否存活的,可達性分析演算法理論上要求全過程都基於一個能保障一致性的快照中才能夠進行分析,這意味著必須全程凍結用戶線程的運行。 在根節點枚舉這個步驟中,由於 GC Roots 相比起整個 Java 堆中全部的對象畢竟還算是極少數,且在各 ...
  • 大家好,我是三友~~ 前幾天有個大兄弟問了我一個問題,註冊中心要集成SpringCloud,想實現SpringCloud的負載均衡,需要實現哪些介面和規範。 既然這個兄弟問到我了,而我又剛好知道,這不得好好寫一篇文章來回答這個問題,雖然在後面的聊天中我已經回答過了。 接下來本文就以探究一下Nacos ...
  • 列印九九乘法表 for i in range(1, 10): for j in range(1, i+1): print(i, "x", j, "=", i * j, end=' ') print("\n") 第三行的 print(i, "x", j, "=", i * j, end=' ') 列印 ...
  • 前言: 在UI自動化測試和爬蟲測試中,驗證碼是個比較頭疼的問題,包括:圖片驗證碼,滑塊驗證碼,等一些常見的驗證碼場景。 識別驗證碼的python 庫有很多,用起來也並不簡單,這裡推薦一個簡單實用的識別驗證碼的庫 ddddocr (帶帶弟弟ocr)庫。 今天先用一個圖片驗證碼示例來演示下: 準備: 1 ...
  • 前言 之前通過github學習了一個.net core的博客項目,最近也是完成了博客的備案,完善了一下。該項目是傳統的MVC項目,可以進行主題的切換,採用Bootstrap進行前臺頁面的展示,有配套的後臺管理系統,可以解析Markdown文件。 參觀地址 ZY知識庫 可以將個人的意見評論到該文章,我 ...
  • 話接上篇 [ASP.NET Core - 緩存之記憶體緩存(上)],所以這裡的目錄從 2.4 開始。 2.4 MemoryCacheEntryOptions MemoryCacheEntryOptions 是記憶體緩存配置類,可以通過它配置緩存相關的策略。除了上面講到的過期時間,我們還能夠設置下麵這些: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...