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


微信公眾號: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


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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM