WPF中使用CallerMemberName简化InotifyPropertyChanged的实现

 更新时间:2022年06月20日 11:56:05   作者:天方  
这篇文章介绍了WPF中使用CallerMemberName简化InotifyPropertyChanged的实现,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

在WPF中,当我们要使用MVVM的方式绑定一个普通对象的属性时,界面上往往需要获取到属性变更的通知,

    class NotifyObject : INotifyPropertyChanged
    {
        private int number;
        public int Number
        {
            get { return number; }
            set { number = value; OnPropertyChanged("Number"); }
        }

        private string text;
        public string Text
        {
            get { return text; }
            set { text = value; OnPropertyChanged("Text"); }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName = "")
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

这么做有一个比较大的隐患,那就是用了字符串的硬编码的方式传递了属性名称,一旦拼写错误或因为重构代码忘记去更新这个字符串时,这样就会导致界面上得不到更新。(本身硬编码的方式来保证两者的一致性就是不靠谱的行为)

虽然这本身并不是问题,但却不是很好的实践。也有人通过一些手段来解决这个问题,有的是通过表达式树,还有的通过Attribute注入的方式。

从性能上来讲,注入是一个比较好的方式,但往往引入了比较复杂的框架。实际上,在C# 5.0中就引入了一个调用方信息的语法方便我们获取调用方的函数名称和位置,通过它可以非常简单快捷的解决上面的这个问题:

    class NotifyObject : INotifyPropertyChanged
    {
        private int number;
        public int Number
        {
            get { return number; }
            set { number = value; OnPropertyChanged(); }
        }

        private string text;
        public string Text
        {
            get { return text; }
            set { text = value; OnPropertyChanged(); }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

代码很简单,这里就不多介绍了。

更进一步

有的时候,为了减少通知的频率,往往会把通知写出如下形式:

    private int number;
    public int Number
    {
        get { return number; }
        set
        {
            if (number == value)
                return;

            number = value;
            OnPropertyChanged();
        }
    }

    private string text;
    public string Text
    {
        get { return text; }
        set
        {
            if (text == value)
                return;

            text = value;
            OnPropertyChanged();
        }
    }

这种写法非常单调,并且在属性多的时候代码就显得很累赘了。这里我就写了一个通用点的函数把他们统一起来,下次就可以直接用了。

    private int number;
    public int Number
    {
        get { return number; }
        set { UpdateProper(ref number, value); }
    }

    private string text;
    public string Text
    {
        get { return text; }
        set { UpdateProper(ref text, value); }
    }

    protected void UpdateProper<T>(ref T properValue, T newValue, [CallerMemberName] string properName = "")
    {
        if (object.Equals(properValue, newValue))
            return;

        properValue = newValue;
        OnPropertyChanged(properName);
    }

由于C#的语法限制,不能在类外部调用event,因此不能写成扩展方法,这里就简单的写成一个对象,下次就直接照着改好了:

    class NotifyObject : INotifyPropertyChanged
    {
        private int number;
        public int Number
        {
            get { return number; }
            set { UpdateProper(ref number, value); }
        }

        private string text;
        public string Text
        {
            get { return text; }
            set { UpdateProper(ref text, value); }
        }

        protected void UpdateProper<T>(ref T properValue, T newValue, [CallerMemberName] string properName = "")
        {
            if (object.Equals(properValue, newValue))
                return;

            properValue = newValue;
            OnPropertyChanged(properName);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

到此这篇关于WPF中使用CallerMemberName简化InotifyPropertyChanged的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C# mysql 插入数据,中文乱码的解决方法

    C# mysql 插入数据,中文乱码的解决方法

    用C#操作mysql时, 插入数据中文都是乱码,只显示问号,数据库本身使用的是utf-8字符
    2013-10-10
  • c#判断代码是否执行超时的几种方式总结

    c#判断代码是否执行超时的几种方式总结

    这篇文章主要介绍了c#判断代码是否执行超时的几种方式总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • C#中WinForm控件的拖动和缩放的实现代码

    C#中WinForm控件的拖动和缩放的实现代码

    本篇文章主要介绍了C#中WinForm控件的拖动和缩放的实现代码,C# WinForm控件的拖动和缩放是个很有用的功能,有兴趣的可以了解一下。
    2017-01-01
  • C#中使用IFormattable实现自定义格式化字符串输出示例

    C#中使用IFormattable实现自定义格式化字符串输出示例

    这篇文章主要介绍了C#中使用IFormattable实现自定义格式字符串输出示例,本文直接给出实例代码,需要的朋友可以参考下
    2015-06-06
  • DataGridView控件显示行号的正确代码及分析

    DataGridView控件显示行号的正确代码及分析

    今天要用到DataGridView,想给它动态的显示行号。于是在网上找了一下解决方法。结果发现了不少问题。然而就是这么一段有错的代码,几乎充斥着整个互联网,千篇一律的COPY,没有一个人纠正
    2013-08-08
  • C#序列化与反序列化实例

    C#序列化与反序列化实例

    这篇文章主要介绍了C#序列化与反序列化的实现方法,实例分析了序列化与反序列化的原理与实现技巧,需要的朋友可以参考下
    2015-01-01
  • C#验证码识别类完整实例

    C#验证码识别类完整实例

    这篇文章主要介绍了C#验证码识别类,以一个完整实例形式较为详细的分析了验证码图片处理所涉及的各种常用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • 利用C#实现AOP常见的几种方法详解

    利用C#实现AOP常见的几种方法详解

    AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。下面这篇文章主要给大家介绍了关于利用C#实现AOP常见的几种方法,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-09-09
  • WinForm实现拦截窗体上各个部位的点击特效实例

    WinForm实现拦截窗体上各个部位的点击特效实例

    这篇文章主要介绍了WinForm实现拦截窗体上各个部位的点击特效实例,对窗体上各个部位进行定义,从而实现了点击特效,需要的朋友可以参考下
    2014-09-09
  • c# 进程内部的同步

    c# 进程内部的同步

    这篇文章主要介绍了c# 进程内部的同步,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下
    2020-10-10

最新评论