zoukankan      html  css  js  c++  java
  • 简化MVVM属性设置和修改

    微信公众号: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


    时间如流水,只能流去不流回!

    这段时间在家,除了睡觉,也不要忘了学习。

  • 相关阅读:
    How to Analyze Java Thread Dumps
    Attention to encodings
    Inspect Memory Leak
    Java boolean operator &=, |= and ^=
    网站PC端和移动端,用户通过设备识别
    网页平滑过渡效果和自适用,三角图形,动效
    开机自动调用.bat文件且浏览器全屏展示
    react中使用屏保
    Axios的get和post请求写法
    React在componentWillMount中请求接口数据结束后再执行render
  • 原文地址:https://www.cnblogs.com/Dotnet9-com/p/12283434.html
Copyright © 2011-2022 走看看