【WPF】聊聊WPF中INotifyPropertyChanged [TOC]
聊聊WPF中INotifyPropertyChanged
文章目录
- 聊聊WPF中INotifyPropertyChanged
- 一、INotifyPropertyChanged接口
- 二、DataContext
- 2.1/DataContext作用
- 2.2/DataContext特性
- 2.3/DataContext实例
- 三、INotifyPropertyChanged接口的几种实现方式
- 3.1/简单INotifyPropertyChanged绑定
- 3.2/使用Lambda表达式,静态扩展语法
- 3.3/Net4.5,框架提供的解决方法
- 四、INotifyPropertyChanged总结
一、INotifyPropertyChanged接口
在Windows Presentation Foundation(WPF)中,INotifyPropertyChanged是一个核心接口,用于实现类与视图之间的数据双向绑定。当实体类的某个属性值发生变化时,通过实现此接口可以立即通知绑定到属性的所有UI控件进行更新,ICommand主要针对的是关联到任何实现了ICommand接口的对象的方法。
在C#中,CallerMemberName是.NET框架提供的一个编译器特性(Compiler Feature),它允许你获取调用当前方法的成员名称,而无需硬编码该名称。这对于实现INotifyPropertyChanged接口特别有用,因为它可以减少手动输入属性名的工作量,提高代码的健壮性和可维护性。
不管是ICommand还是INotifyPropertyChanged都必须首先将ViewMode的实现设置为控件或整个界面的DataContext。如:
this.DataContext = new MainViewModel();
DataContext是UI层与数据逻辑层的桥梁
二、DataContext
DataContext是一个非常关键的概念,它是实现数据绑定的基础。DataContext是所有WPF控件都具有的一个依赖属性。它属于System.Windows.FrameworkElement类。这意味着所有继承自该类的控件都可以使用DataContext。
2.1/DataContext作用
DataContext作为一个容器,提供了UI层和数据层之间的连接点。在MVVM(Model-View-ViewModel)架构模式中,通常将ViewModel设置为控件或整个界面的DataContext,这样UI控件可以通过绑定直接访问ViewModel中的数据和命令。
2.2/DataContext特性
- 继承性:DataContext具有继承特性,子控件如果没有明确设置自身的DataContext,则会从其元素继承DataContext的值。这意味着在整个控件树中可以共享同一个数据上下文对象。
- 数据绑定:在WPF中,当你写一个数据绑定表达式如{Binding Path=PropertyName}时,默认情况下,Binding将查找当前元素的DataContext,并在其中寻找指定路径的属性。
- 实现数据驱动视图:通过将业务逻辑对象或ViewModel对象设置为控件或整个界面的DataContext,WPF可以自动根据这些对象中的数据变化更新相关联的用户界面元素。
2.3/DataContext实例
<Window><Window.DataContext><local:MyViewModel/></Window.DataContext><StackPanel><TextBox Text="{Binding Name}" /><Button Command="{Binding SaveCommand}" Content="Save" /></StackPanel>
</Window>
上面的示例,Window的DataContext被设置为了MyViewModel实例,因为TextBox和Button都可以通过数据绑定访问到MyViewModel中的Name属性和SaveCommand命令。
三、INotifyPropertyChanged接口的几种实现方式
3.1/简单INotifyPropertyChanged绑定
- 定义实例类并继承接口INotifyPropertyChanged
public class Person:INotifyPropertyChanged
{private string m_Name="默认值是XXXX";public string Name {get =>m_Name;set{if (m_Name == value) return;m_Name = value;this.Notify("Name");}}public event PropertyChangedEventHandler PropertyChanged;public void Notify(string propertyName) {PropertyChangedEventHandler handler = this.PropertyChanged;if(handler!=null)handler(this, new PropertyChangedEventArgs(propertyName));}
}
- 界面绑定ViewModel
<Window x:Class="WpfToolkitApp.WinMvvmFirst"...xmlns:vm="clr-namespace:WpfToolkitApp.Model"><Window.DataContext><vm:Person></vm:Person></Window.DataContext><Grid><Label Content="名称" HorizontalAlignment="Left" Margin="21,104,0,0" VerticalAlignment="Top"/><TextBox HorizontalAlignment="Left" Margin="60,104,0,0" TextWrapping="Wrap"Text="{Binding Name}" VerticalAlignment="Top" Width="221" Height="25"/></Grid>
</Window>
- 界面构造函数绑定DataContext
public partial class WinMvvmFirst : Window
{Person person = null;public WinMvvmFirst(){InitializeComponent();person = base.DataContext as Person;}
}
3.2/使用Lambda表达式,静态扩展语法
public static class NotificationExtensions{public static void Notify(this PropertyChangedEventHandler eventHandler, Expression<Func<object>> expression) {if (eventHandler == null) {return;}var lambda = expression as LambdaExpression;MemberExpression memberExpression;if (lambda.Body is UnaryExpression){var unaryExpression = lambda.Body as UnaryExpression;memberExpression = unaryExpression.Operand as MemberExpression;}else {memberExpression = lambda.Body as MemberExpression;}var constantExpression = memberExpression.Expression as ConstantExpression;var propertyInfo = memberExpression.Member as PropertyInfo;foreach (var del in eventHandler.GetInvocationList()){del.DynamicInvoke(new object[] { constantExpression.Value, new PropertyChangedEventArgs(propertyInfo.Name) });}}}
静态扩展方法使用:
public class Employee : INotifyPropertyChanged
{public event PropertyChangedEventHandler PropertyChanged;private string _trueName;public string TrueName{get{return this._trueName}set{this._trueName = value;this.PropertyChanged.Notify(()=>this.TrueName);}}}
还可以添加一个很实用的扩展:
public static void SubscribeToChange<T>(this T objectThatNotifies, Expression<Func<object>> expression, PropertyChangedEventHandler<T> handler) where T :INotifyPropertyChanged
{objectThatNotifies.PropertyChanged +=(s, e) =>{var lambda = expression as LambdaExpression;MemberExpression memberExpression;if (lambda.Body is UnaryExpression){var unaryExpression = lambda.Body as UnaryExpression;memberExpression = unaryExpression.Operand as MemberExpression;}else{memberExpression = lambda.Body as MemberExpression;}var propertyInfo = memberExpression.Member as PropertyInfo;if (e.PropertyName.Equals(propertyInfo.Name)){handler(objectThatNotifies);}};
}
3.3/Net4.5,框架提供的解决方法
private string m_myProperty;
public string MyProperty
{get{return m_myProperty;}set{m_myProperty = value;OnPropertyChanged();}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = "none passed")
{}
属性CallerMemberName的解决办法和方法二是基本相同的,不同的这个在net框架中解决的。更多信息可以查看CallerMemberName,Net4.5还提供了CallerFilePath、CallerLineNumber,稍微会详细讲解。
四、INotifyPropertyChanged总结
INotifyPropertyChanged接口用于向客户端发出某一属性值已更改的通知。在应用有两种方式OneTime模式、OneWay模式和TwoWay模式。
- OneTime模式
OneTime模式是一个初始化一次绑定。不常用。
- OneWay模式
绑定源的每一次变化都会通知绑定目标,但是绑定目标的改变不会改变绑定源。当绑定源的数据实体类没有实现INotifyPropertyChanged接口时,当改变了数据源,发现绑定目录的UI上的相应的数据不会立即变化。
- TwoWay模式
TwoWay模式下,当绑定源的数据实体类没有实现INotifyPropertyChanged接口时,空间的更改会让数据源立即发改变,但是改变数据源,绑定目标控件却不会立即发送改变,所以当我们需要数据源改变时相对应的UI立即改变时,需要实现INotifyPropertyChanged接口。
相关文章:
【WPF】聊聊WPF中INotifyPropertyChanged [TOC]
聊聊WPF中INotifyPropertyChanged 文章目录 聊聊WPF中INotifyPropertyChanged一、INotifyPropertyChanged接口二、DataContext2.1/DataContext作用2.2/DataContext特性2.3/DataContext实例 三、INotifyPropertyChanged接口的几种实现方式3.1/简单INotifyPropertyChanged绑定3.2…...
SpringBoot Actuator未授权访问漏洞的解决方法
1. 介绍 Spring Boot Actuator 是一个用于监控和管理 Spring Boot 应用程序的功能模块。它提供了一系列生产就绪的功能,帮助你了解应用程序的运行状况,以及在运行时对应用程序进行调整。Actuator 使用了 Spring MVC 来暴露各种 HTTP 或 JMX 端点&#x…...
AI大模型探索之路-训练篇18:大语言模型预训练-微调技术之Prompt Tuning
系列篇章💥 AI大模型探索之路-训练篇1:大语言模型微调基础认知 AI大模型探索之路-训练篇2:大语言模型预训练基础认知 AI大模型探索之路-训练篇3:大语言模型全景解读 AI大模型探索之路-训练篇4:大语言模型训练数据集概…...
Ollamallama
Olllama 直接下载ollama程序,安装后可在cmd里直接运行大模型; llama 3 meta 开源的最新llama大模型; 下载运行 1 ollama ollama run llama3 2 github 下载仓库,需要linux环境,windows可使用wsl; 接…...
苹果Mac用户下载VS Code(Universal、Intel Chip、Apple Silicon)哪个版本?
苹果macOS用户既可以下载通用版(Universal),软件将自动检测用户的处理器并进行适配。 也可以根据型号下载对应CPU的版本: 使用Intel CPU的Mac电脑可下载Intel Chip版本; 使用苹果自研M系列CPU的Mac电脑下载Apple Si…...
Linux(Ubuntu)安装CGAL(非root)
一、安装boost 下载地址:Boost C Libraries - Browse /boost at SourceForge.net 我安装的是1.77.0的版本 ./bootstrap.sh --prefix/usr/local/boost ./b2 ./b2 install 配置环境变量 vim ~/.bashrcexport BOOST_INCLUDE/usr/local/boost/include export BO…...
hadoop学习---基于Hive的教育平台数据仓库分析案例(三)
衔接第一部分,第一部分请点击:基于Hive的教育平台数据仓库分析案例(一) 衔接第二部分,第二部分请点击:基于Hive的教育平台数据仓库分析案例(二) 学生出勤模块(全量分析):…...
RAFT:引领 Llama 在 RAG 中发展
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
上海亚商投顾:沪指缩量调整 合成生物概念股持续爆发
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 沪指昨日缩量震荡调整,深成指、创业板指均跌超1%。细胞免疫治疗概念股大涨,冠昊生物、…...
Maven+Junit5 + Allure +Jenkins 搭建 UI 自动化测试实战
文章目录 效果展示Junit 5Junit 5 介绍Junit 5 与 Junit 4 对比PageFactory 模式编写自动化代码公共方法提取测试用例参数化Jenkins 搭建及配置参数化执行生成 Allure 报告Maven 常用命令介绍POM 文件效果展示 本 chat 介绍 UI 自动化测试框架的搭建: 运用 page factory 模式…...
docker学习笔记(三)搭建NFS服务实验
目录 什么是NFS 简单架构编辑 一.搭建nfs服务器 二.新建共享目录和网页文件 三.设置共享目录 四:创建使用nfs共享目录的卷 五:创建容器使用nfs-web-1卷 六:测试访问 七:是否同步测试 什么是NFS NFS 服务器:ne…...
super关键字
super关键字 在Java中,super是一个关键字,它用于引用当前对象的父类。在继承的关系中,子类可以通过super关键字来调用父类的构造方法、成员方法和成员变量。 super关键字的主要用途 调用父类的构造方法: 在子类的构造方法中&…...
【经典算法】LeetCode 200. 岛屿数量(Java/C/Python3/Go实现含注释说明,中等)
目录 题目描述思路及实现方式一:深度优先搜索(DFS)思路代码实现Java版本C语言版本Python3版本Golang版本 复杂度分析 方式二: 使用广度优先搜索(BFS)思路代码实现Java实现C实现Python3实现Go实现 总结相似题…...
Hive SQL-DQL-Select查询语句用法详解
HQL Select用法详解 1.基础语法 (1)select_exp (2)ALL、DISTINCT (3)WHERE (4)分区查询、分区裁剪 (5)GROUP BY (6)HAVING ࿰…...
沙盘Sandboxie v5.56.4
菜鸟高手裸奔工具沙盘Sandboxie是一款国外著名的系统安全工具,它可以让选定程序在安全的隔离环境下运行, 只要在此环境中运行的软件,浏览器或注册表信息等都可以完整的进行清空,不留一点痕迹。同时可以防御些 带有木马或者病毒的…...
Arcpy开发记录
一.GDB数据库相关 1.单独的shape更新时,不会有限制,数据会自动截取 2.在GDB下,使用UpdateCursor更新字段时,填入的数据长度必须与字段长度要求一致,否则报错: 二.Cursor相关 嵌套使用cursor时,…...
Android使用itextpdf操作PDF文档
1、导入jar包: itext-asian.jaritextpdf-5.5.8.jar Paragraph 和 Phrase 的区别: 在 iTextPDF 库中,Paragraph 和 Phrase 是用于创建和组织文本内容的两个不同的类。 Paragraph(段落): Paragraph 是一个…...
llama_index微调BGE模型
微调模型是为了让模型在特殊领域表现良好,帮助其学习到专业术语等。 本文采用llama_index框架微调BGE模型,跑通整个流程,并学习模型微调的方法。 已开源:https://github.com/stay-leave/enhance_llm 一、环境准备 Linux环境,GPU L20 48G,Python3.8.10。 pip该库即可。…...
什么是限流?常见的限流算法
目录 1. 什么是限流 2. 常见限流算法 3. 固定窗口算法 4. 滑动窗口算法 5. 漏桶算法 6. 令牌桶算法 7. 限流算法选择 1. 什么是限流 限流(Rate Limiting)是一种应用程序或系统资源管理的策略,用于控制对某个服务、接口或功能的访问速…...
ZL-0895小动物活动记录仪可同时检测8只动物的活动量
简单介绍: 小动物活动记录仪是一种多用途、宽范围的小动物活动记录仪器,可用于小鼠、大鼠、豚鼠和兔的实验,小动物活动记录仪具有不需对动物使用特别盛具的特点,可在不改变动物原生活环境的情况下,进行实时监测&…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...
从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
