WPF中使用CallerMemberName简化InotifyPropertyChanged的实现

作者:天方 时间:2023-05-08 16:27:07 

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

来源:https://www.cnblogs.com/TianFang/p/3381484.html

标签:WPF,CallerMemberName,简化,InotifyPropertyChanged
0
投稿

猜你喜欢

  • 使用C# Winform应用程序获取网页源文件的解决方法

    2023-02-01 10:56:28
  • 详解Java中List的正确的删除方法

    2021-09-19 13:20:42
  • C#多线程爬虫抓取免费代理IP的示例代码

    2023-02-08 01:22:01
  • C#递归算法之归并排序

    2023-01-01 14:49:36
  • Android开发实现读取Assets下文件及文件写入存储卡的方法

    2023-02-07 15:42:21
  • java.util.NoSuchElementException原因及两种解决方法

    2022-02-10 15:18:58
  • 浅析java实现数据加密问题

    2023-03-21 02:54:04
  • Java并发编程之详解CyclicBarrier线程同步

    2023-08-01 14:08:47
  • c# 防火墙添加/删除 特定端口的示例

    2023-12-22 21:56:41
  • Android实现简单的分批加载ListView

    2023-10-28 14:49:21
  • Android开发Retrofit源码分析

    2022-06-11 18:19:07
  • C#中的事务用法实例分析

    2022-04-03 05:23:37
  • Android获取当前已连接的wifi信号强度的方法

    2023-06-21 22:11:45
  • java语言注解基础概念详解

    2023-04-13 06:55:55
  • Spring Cloud 请求重试机制核心代码分析

    2023-04-11 04:00:23
  • 浅谈SpringCloud实现简单的微服务架构

    2023-05-22 12:59:34
  • IDEA 2020.2 +Gradle 6.6.1 + Spring Boot 2.3.4 创建多模块项目的超详细教程

    2021-11-08 00:42:36
  • java使用链表实现约瑟夫环

    2022-03-21 18:59:35
  • SpringBoot+Vue项目新手快速入门指南

    2023-05-20 04:56:07
  • java实现登录验证码功能

    2021-06-08 19:34:18
  • asp之家 软件编程 m.aspxhome.com