簡化MVVM屬性設置和修改 - .NET CORE(C#) WPF開發

来源:https://www.cnblogs.com/Dotnet9-com/archive/2020/02/08/12283434.html
-Advertisement-
Play Games

微信公眾號: "Dotnet9" ,網站: "Dotnet9" ,問題或建議: "請網站留言" , 如果對您有所幫助: "歡迎贊賞" 。 簡化MVVM屬性設置和修改 .NET CORE(C ) WPF開發 閱讀導航 1. 常用類屬性設置、獲取方式 2. 二次封裝 INotifyPropertyCha ...


微信公眾號:Dotnet9,網站:Dotnet9,問題或建議:請網站留言
如果對您有所幫助:歡迎贊賞

簡化MVVM屬性設置和修改 - .NET CORE(C#) WPF開發

閱讀導航

  1. 常用類屬性設置、獲取方式
  2. 二次封裝 INotifyPropertyChanged
  3. Demo 展示、源碼下載

1. 常用類屬性設置、獲取方式

public class Student : INotifyPropertyChanged
{
    private string name;
    public string Name
    {
        get { return name; }
        set
        {
            if(name != value)
            {
                name = value;
                OnPropertyChanged("Name")
            }
        }
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}

這種方式總感覺有點啰嗦,如果 Name 屬性名修改,字元串 "Name" 還要手動修改,就算 Ctrl+H 替換也容易出錯,如果使用下麵這種方式,是不是感覺更清爽一點?

public class Student : PropertyNotifyObject
{
    public string Name    
    {
        get { return this.GetValue(cu => cu.Name); }
        set { this.SetValue(cu => cu.Name, value); }
    }
}

2. 二次封裝INotifyPropertyChanged

封裝的基類PropertyNotifyObject出處我忘了,15年網上找的,源碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Threading;

namespace MVVMTest
{

    #region 封裝WPF屬性

    public class MyCommMetoh
    {
        //得到屬性的名稱
        public static string GetPropertyName<T, U>(Expression<Func<T, U>> exp)
        {
            string _pName = "";
            if (exp.Body is MemberExpression)
            {
                _pName = (exp.Body as MemberExpression).Member.Name;
            }
            else if (exp.Body is UnaryExpression)
            {
                _pName = ((exp.Body as UnaryExpression).Operand as MemberExpression).Member.Name;
            }
            return _pName;
        }
    }

    public class NotifyPropertyBase : INotifyPropertyChanged
    {
        /// <summary>
        /// Returns a dispatcher for multi-threaded scenarios
        /// </summary>
        /// <returns></returns>
        public static Dispatcher GetDispatcher(DispatcherObject source = null)
        {
            //use the application's dispatcher by default
            if (Application.Current != null) return Application.Current.Dispatcher;

            //fallback for WinForms environments
            if (source != null && source.Dispatcher != null) return source.Dispatcher;

            //ultimatively use the thread's dispatcher
            return Dispatcher.CurrentDispatcher;
        }

        #region INotifyPropertyChanged
        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                GetDispatcher().BeginInvoke((Action)delegate
                    {
                        try
                        {
                            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                        }
                        catch (Exception ex)
                        {
                            var msg = string.Format("發送UI屬性變化事件異常,屬性名稱: {0}, 異常詳細信息: {1}", propertyName, ex.ToString());
                        }
                    }
                );

            }
        }
        public void OnPropertyChanged<T>(Expression<Func<T>> expression)
        {
            if (PropertyChanged != null)
            {
                var propertyName = ((MemberExpression)expression.Body).Member.Name;
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
    }
    public static class NotifyPropertyBaseEx
    {
        public static void OnPropertyChanged<T, U>(this T npb, Expression<Func<T, U>> exp) where T : NotifyPropertyBase, new()
        {
            string _PropertyName = MyCommMetoh.GetPropertyName(exp);
            npb.OnPropertyChanged(_PropertyName);
        }
    }

    public class PropertyNotifyObject : NotifyPropertyBase, IDisposable
    {
        public PropertyNotifyObject()
        {
        }

        Dictionary<object, object> _ValueDictionary = new Dictionary<object, object>();

        #region 根據屬性名得到屬性值
        public T GetPropertyValue<T>(string propertyName)
        {
            if (string.IsNullOrEmpty(propertyName)) throw new ArgumentException("invalid " + propertyName);
            object _propertyValue;
            if (!_ValueDictionary.TryGetValue(propertyName, out _propertyValue))
            {
                _propertyValue = default(T);
                _ValueDictionary.Add(propertyName, _propertyValue);
            }
            return (T)_propertyValue;
        }
        #endregion

        public void SetPropertyValue<T>(string propertyName, T value)
        {
            if (!_ValueDictionary.ContainsKey(propertyName) || _ValueDictionary[propertyName] != (object)value)
            {
                _ValueDictionary[propertyName] = value;
                OnPropertyChanged(propertyName);
            }
        }

        #region Dispose
        public void Dispose()
        {
            DoDispose();
        }
        ~PropertyNotifyObject()
        {
            DoDispose();
        }
        void DoDispose()
        {
            if (_ValueDictionary != null)
                _ValueDictionary.Clear();
        }
        #endregion
    }
    public static class PropertyNotifyObjectEx
    {
        public static U GetValue<T, U>(this T t, Expression<Func<T, U>> exp) where T : PropertyNotifyObject
        {
            string _pN = MyCommMetoh.GetPropertyName(exp);
            return t.GetPropertyValue<U>(_pN);
        }

        public static void SetValue<T, U>(this T t, Expression<Func<T, U>> exp, U value) where T : PropertyNotifyObject
        {
            string _pN = MyCommMetoh.GetPropertyName(exp);
            t.SetPropertyValue<U>(_pN, value);
        }
    }

    #endregion
}

3. Demo展示、源碼下載

源碼下載:MVVMTest

展示效果:效果

除非註明,文章均由 Dotnet9 整理髮布,歡迎轉載。

轉載請註明本文地址:https://dotnet9.com/8572.html

歡迎掃描下方二維碼關註 Dotnet9 的微信公眾號,本站會及時推送最新技術文章

Dotnet9


時間如流水,只能流去不流回!

這段時間在家,除了睡覺,也不要忘了學習。


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

-Advertisement-
Play Games
更多相關文章
  • 數據類型(二) 今日內容 1、列表 2、元組 內容回顧和補充 1、電腦基礎 ①硬體:cpu,記憶體,硬碟,主板,網卡 ②操作系統:linux,centos, Ubuntu,redhat windows mac ③解釋器,編譯器 補充:編譯型語言和解釋型語言 編譯型:寫完代碼後,編譯器一次性編譯交給計 ...
  • 在頁面進行後臺資料庫操作的時候,不想 用戶再進行 頁面上的 其他操作,這時候就要 將頁面 遮罩。 1]使用ScreenMask函數 2]JS調用 1]使用ScreenMask函數 ScreenMask.Color:=clGreen; // 顏色 ScreenMask.Enabled:=True; / ...
  • Eclipse是Java的“集成開發環境”(IDE).當然也可作為其它語言的集成開發環境,如C,C++,PHP,和 Ruby 等。 一、Windows下安裝Eclipse 安裝Eclipse前一定要確保電腦上已經裝了JDK。如果未安裝,請前往:http://www.oracle.com/techne ...
  • 更新記錄 【1】2020.02.08 16:37 1.完善內容 正文 我正在看內部類與介面的時候,突然萌生出一個想法:抽象類中能不能嵌套介面呢? 於是我準備試一試: 沒想到,這種寫法竟然被認可 經過一番分析後覺得是有道理的 那麼問題來了:怎麼實現介面呢? 其實這和內部類很像,只要分別實現抽象類與介面 ...
  • 前言: 圖論乃noip之重要知識點,但有點難理解 本人因此吃過不少虧 因為本人實在太弱,所以此篇乃正宗<蒟蒻專屬文章> 正文:(本文僅介紹圖論中的重點、難點,其餘部分略將或不講) 圖一般來說有二種存儲方法:鄰接矩陣和鄰接表 鄰接矩陣: 存儲:拿二維數組來存 for(int i=1;i<=n;++i) ...
  • 前面章節已經對命令進行了深入分析,分析了基類和介面以及WPF提供的命令庫。但尚未例舉任何使用這些命令的例子。 如前所述,RoutedUICommand類沒有任何硬編碼的功能,而是只表達命令,為觸發命令,需要有命令源(也可使用代碼)。為響應命令,需要有命令綁定,命令綁定將執行轉發給普遍的事件處理程式。 ...
  • ASP.NET Core 應用是在其 Main 方法中創建 Web 伺服器的控制台應用: Main 方法調用 WebHost.CreateDefaultBuilder,通過生成器模式來創建web主機.生成器提供定義 Web 伺服器(例如,UseKestrel)和啟動類 (UseStartup) 的方 ...
  • 背景: 測試部署NetCore 項目到linux 系統時,視窗顯示項目部署成功;但是本機無法訪問(linux 在虛擬機上[ centos 7.6] ); 如下圖↓ 能夠相互ping 通,(Xshell 連接正常。),在centos 上 也能正常訪問,後來記起在進行linux 安裝成功後,沒有關閉防火 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...