在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));
            }
        }
    }

使用CallerMemberName简化InotifyPropertyChanged的实现的更多相关文章

  1. [转]使用CallerMemberName简化InotifyPropertyChanged的实现

    原文:https://www.cnblogs.com/TianFang/p/3381484.html 在WPF中,当我们要使用MVVM的方式绑定一个普通对象的属性时,界面上往往需要获取到属性变更的通知 ...

  2. C# 特性学习之一、CallerMemberName、CallerFilePath和CallerLineNumber

    在开发中经常会写个公有静态类记录日志,如下: /// <summary> /// Writes the error. /// </summary> /// <param ...

  3. 如何优雅的实现INotifyPropertyChanged接口

    INotifyPropertyChanged接口在WPF或WinFrom程序中使用还是经常用到,常用于通知界面属性变更.标准写法如下: class NotifyObject : INotifyProp ...

  4. 转载:如何优雅的实现INotifyPropertyChanged接口

    转载来源:http://www.cnblogs.com/TianFang/p/6240933.html 如何优雅的实现INotifyPropertyChanged接口 INotifyPropertyC ...

  5. C# 5.0中使用CallerMemberName、CallerFilePath和CallerLineNumber获取代码的调用方信息(转载)

    很多时候,我们需要在运行过程中记录一些调测的日志信息,如下所示: public void DoProcessing() { TraceMessage("DoProcessing()被XXX调 ...

  6. C# 各版本新特性

    C# 2.0 泛型(Generics) 泛型是CLR 2.0中引入的最重要的新特性,使得可以在类.方法中对使用的类型进行参数化. 例如,这里定义了一个泛型类: class MyCollection&l ...

  7. C# 5.0中新增特性

    C# 5.0随着VisualStudio 2012一起正式发布了,让我们来看看C#5.0中增加了哪些功能. 1. 异步编程 在.Net 4.5中,通过async和await两个关键字,引入了一种新的基 ...

  8. C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) C#各版本新特性 C#版本和.NET版本以及VS版本的对应关系

    C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) 2017年08月06日 11:53:13 阅读数:6705 历史版本 C#作为微软2000年以后.NET平台开发的当家语言,发展至今具有1 ...

  9. C# 5.0新加特性

    1. 异步编程 在.Net 4.5中,通过async和await两个关键字,引入了一种新的基于任务的异步编程模型(TAP).在这种方式下,可以通过类似同步方式编写异步代码,极大简化了异步编程模型.如下 ...

随机推荐

  1. Lucene系列-索引文件

    本文介绍下lucene生成的索引有哪些文件组成,每个文件包含了什么信息.基于Lucene 4.10.0. 数据结构 索引(index)包含了存储的文档(document)正排.倒排信息,用于文本搜索. ...

  2. IOS UIView 02- 深入理解 Scroll Views

    注:本人是翻译过来,并且加上本人的一点见解. 前言 可能你很难相信 UIScrollView 和一个标准的 UIView 差异并不大,scroll view 确实会多出一些方法,但这些方法只是和 UI ...

  3. 我也说百度和google

    对于程序员,最好的老师恐怕还是百度或者google或一些专业的it社区.网站了罢! 之前曾听到这样的一句话, 文艺程序员用Google Scholar/Scirus/stackoverflow.普通程 ...

  4. MVVM架构~mvc,mvp,mvvm大话开篇

    返回目录 百度百科的定义: MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新 ...

  5. Eclipse 工程迁移到 Android Studio

    目标:迁移成功,并成功正常运行! 附加:同步视频在文章后面! 两种方式: 1. 用Gradle导出,在Android Studio中用Gradle导入 (不推荐) 2. 用Android Studio ...

  6. Atitit 知识图谱解决方案:提供完整知识体系架构的搜索与知识结果overview

    Atitit 知识图谱解决方案:提供完整知识体系架构的搜索与知识结果overview   知识图谱的表示和在搜索中的展1 提升Google搜索效果3 1.找到最想要的信息.3 2.提供最全面的摘要.4 ...

  7. (Task)任务异步(TAP)的使用

    任务有返回值例子: using System; using System.Collections.Generic; using System.Linq; using System.Text; usin ...

  8. vue-cli创建项目

  9. Apache多站点实现原理和配置

    Apache多站点实现原理 很多人常常看到一台服务器上跑多个站点,不同的域名访问不同的站点,就会有个疑惑:访问的时候并没有在地址栏中加入端口号,多个域名都是解析到这个服务器的IP地址,服务器怎么能够正 ...

  10. 探讨js字符串数组拼接的性能问题

    这篇文章主要介绍了有关js对字符串数组进行拼接的性能问题,字符串连接一直是js中性能最低的操作之一,应该如何解决呢?请参看本文的介绍 我们知道,在js中,字符串连接是性能最低的操作之一. 例如: 复制 ...