news 2026/7/8 4:27:12

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(“Text“));---核心是:INotifyPropertyChanged接口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(“Text“));---核心是:INotifyPropertyChanged接口

一、PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Text"));是什么意思?

这是一个在C#中用于触发属性变更通知的典型代码片段,通常用于实现INotifyPropertyChanged接口。

分解解释:

1.PropertyChanged?

  • PropertyChanged是一个事件(event)

  • ?是C# 6.0引入的空条件运算符(Null-conditional operator)

  • 等价于if (PropertyChanged != null)

  • 防止在事件没有订阅者时抛出NullReferenceException

2.Invoke(this, new PropertyChangedEventArgs("Text"))

  • Invoke: 触发事件的方法

  • this: 当前对象实例(发送通知的对象)

  • new PropertyChangedEventArgs("Text"): 创建事件参数,表示名为"Text"的属性发生了变化

完整上下文示例:

public class ViewModel : INotifyPropertyChanged { private string _text; public string Text { get => _text; set { if (_text != value) { _text = value; // 触发属性变更通知 OnPropertyChanged(nameof(Text)); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { // 这就是你的代码行 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }

主要用途:

数据绑定(WPF/Xamarin/UWP等)

<!-- XAML中 --> <TextBlock Text="{Binding Text}" />

Text属性值改变时,UI会自动更新显示新值。

MVVM模式

  • Model: 数据

  • View: 界面

  • ViewModel: 使用INotifyPropertyChanged连接前两者

为什么需要这样写?

  1. 线程安全?.操作符是线程安全的

  2. 简洁性:一行代码替代了原来的if判断

  3. 解耦:UI不需要知道数据何时变化,只需要订阅变更事件

  4. 自动更新:绑定到该属性的UI控件会自动刷新

等价的老式写法:

if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Text")); }

这种机制是.NET中实现数据驱动UI的核心基础之一。

二、public string Text{}的set方法什么时候被调用?

public string Textset方法在以下几种情况下会被调用:

1.直接赋值(最常见)

var obj = new ViewModel(); obj.Text = "Hello"; // 调用set方法 obj.Text = "World"; // 再次调用set方法

2.对象初始化器

var obj = new ViewModel { Text = "Initial Value" // 调用set方法 };

3.数据绑定(WPF/MVVM中最典型)

<!-- XAML --> <TextBox Text="{Binding Text, Mode=TwoWay}" />

当用户在TextBox中输入内容时:

  • UI控件会自动调用set方法更新ViewModel

  • 然后触发PropertyChanged事件

  • UI根据事件更新显示

实际MVVM场景示例:

public class MainViewModel : INotifyPropertyChanged { private string _text; public string Text { get => _text; set { Console.WriteLine($"Text set被调用,新值: {value}"); if (_text != value) { _text = value; OnPropertyChanged(nameof(Text)); } } } // 命令触发属性更新 public ICommand UpdateTextCommand => new RelayCommand(() => { Text = DateTime.Now.ToString(); // 调用set }); } // XAML中使用 <StackPanel> <!-- 用户输入时调用set --> <TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" /> <!-- 点击按钮时调用set --> <Button Command="{Binding UpdateTextCommand}" Content="更新" /> </StackPanel>

触发set的关键时机:

用户交互时:

  1. 用户在TextBox中输入

  2. 用户选择ComboBox项

  3. 用户勾选CheckBox

  4. 用户滑动Slider等

程序逻辑时:

  1. 从数据库加载数据

  2. 调用API获取响应

  3. 定时器更新

  4. 其他属性变更引发的连锁更新

public class ViewModel : INotifyPropertyChanged { private string _firstName; private string _lastName; private string _fullName; public string FirstName { get => _firstName; set { _firstName = value; OnPropertyChanged(nameof(FirstName)); UpdateFullName(); // 触发其他属性的set } } public string FullName { get => _fullName; set // 可能通过其他方式调用 { _fullName = value; OnPropertyChanged(nameof(FullName)); } } private void UpdateFullName() { FullName = $"{FirstName} {LastName}"; // 调用FullName的set } }

三、PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Text"));执行后,是如何改变UI的?

PropertyChanged?.Invoke(...)执行后,UI不会直接改变,而是通过一个事件订阅机制来间接更新UI。让我详细解释这个过程:

完整的数据绑定流程:

​​​​​​​

1.初始绑定(启动时)

运行

<!-- XAML中建立绑定关系 --> <TextBox Text="{Binding Text}" />

这个过程:

  • WPF绑定系统发现{Binding Text}

  • 查找DataContext中的ViewModel

  • 订阅ViewModel的PropertyChanged事件

  • 建立事件处理器(event handler)

2.事件订阅的伪代码表示

// WPF内部实现的简化版本 public class Binding { private void SubscribeToNotifications() { // 当设置DataContext时,WPF会执行类似代码: if (source is INotifyPropertyChanged inpc) { // 订阅PropertyChanged事件 inpc.PropertyChanged += OnSourcePropertyChanged; } } private void OnSourcePropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Text" || string.IsNullOrEmpty(e.PropertyName)) { UpdateTarget(); // 更新UI控件 } } private void UpdateTarget() { // 通过反射获取新值 var newValue = GetPropertyValue("Text"); // 更新UI控件 SetUIText(newValue); } }

3.实际执行时序

// 1. ViewModel代码 public class ViewModel : INotifyPropertyChanged { private string _text = "Old Value"; public string Text { get => _text; set { _text = value; // 更新值 // 2. 触发事件 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Text")); } } } // 3. WPF内部响应 // PropertyChanged事件触发 → WPF的事件处理器被调用 → UI更新

4.可视化流程

[ 用户输入或代码赋值 ] ↓ [ Text的set方法被调用 ] ↓ [ 字段值更新: _text = value ] ↓ [ 触发PropertyChanged事件 ] ↓ ┌─────────────────┐ │ WPF绑定系统监听到事件 │ └─────────────────┘ ↓ [ 检查属性名是否匹配 ] ↓ [ 通过getter读取新值 ] ↓ [ 调用UI控件的更新方法 ] ↓ [ UI显示更新完成 ]

5.完整的MVVM示例

// ViewModel public class MainViewModel : INotifyPropertyChanged { private string _text; public string Text { get => _text; set { _text = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Text")); } } public ICommand ChangeTextCommand => new RelayCommand(() => { Text = "新文本 " + DateTime.Now.Second; }); } // XAML <Window x:Class="WpfApp.MainWindow" DataContext="{StaticResource MainViewModel}"> <StackPanel> <!-- TextBox绑定到Text属性 --> <TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" Margin="10"/> <!-- Label也绑定到同一个属性 --> <Label Content="{Binding Text}" Background="LightBlue" Padding="10"/> <!-- 按钮触发更新 --> <Button Command="{Binding ChangeTextCommand}" Content="更改文本" Margin="10"/> </StackPanel> </Window>

6.执行按钮点击后的流程

  1. 用户点击按钮

  2. 执行命令Text = "新文本 XX"

  3. 调用set方法_text = "新文本 XX"

  4. 触发事件PropertyChanged?.Invoke(...)

  5. WPF响应

    • TextBox接收到事件 → 更新显示为"新文本 XX"

    • Label接收到事件 → 更新显示为"新文本 XX"

  6. UI完成更新

7.双向绑定示例

<TextBox Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

流程:

用户输入"ABC" → TextBox内容变化 → 触发UpdateSource → 调用ViewModel.Text的set方法 → 触发PropertyChanged事件 → 其他绑定到Text的控件更新

8.多控件同步更新

<!-- 三个控件绑定到同一个属性 --> <TextBox Text="{Binding UserName}"/> <TextBlock Text="{Binding UserName}"/> <Label Content="{Binding UserName}"/> <!-- 当UserName改变时,三个控件同时更新 -->

9.调试技巧

public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { // 添加调试信息 Debug.WriteLine($"属性 {propertyName} 变更,触发事件"); // 查看有多少订阅者 var handler = PropertyChanged; if (handler != null) { Debug.WriteLine($"有 {handler.GetInvocationList().Length} 个订阅者"); } PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }

关键点总结:

  1. 间接更新PropertyChanged.Invoke()不直接更新UI,只是触发事件

  2. 观察者模式:WPF绑定系统是事件的订阅者

  3. 解耦设计:ViewModel不知道UI的具体实现

  4. 自动同步:多个UI控件可以绑定到同一个属性

  5. 性能优化:只有真正需要更新的控件才会响应事件

这种机制实现了数据驱动UI的核心思想:当数据改变时,UI自动响应更新,而不是手动控制UI的每个变化

四、INotifyPropertyChanged 接口

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/7 14:25:03

day35打卡

浙大疏锦行

作者头像 李华
网站建设 2026/7/8 0:48:33

走向场景,走向融合:2025年末国产大模型的平台化竞赛与Agent新范式

目录 1 写作口径与方法&#xff1a;只谈“2025年12月仍在主推/可用”的国产大模型 1.1 为什么必须卡在“2025年12月最新”这个时间点 1.2 “不出现老旧模型”的执行标准 2 2025年末国产大模型的共同转向&#xff1a;从“会写”到“会做” 2.1 语言大模型正在变成“推理与执…

作者头像 李华
网站建设 2026/7/6 6:58:14

【time-rs】Duration 结构体详解

这是一个 Rust 时间库中的 Duration 结构体实现&#xff0c;提供高精度的时间跨度表示。 1. 主要特性 纳秒级精度&#xff1a;由整秒和纳秒部分组成支持负值&#xff1a;与标准库的 std::time::Duration 不同&#xff0c;支持负时间间隔安全边界检查&#xff1a;使用 RangedI32…

作者头像 李华
网站建设 2026/7/5 8:11:21

10398_基于SSM的教学评价管理系统

1、项目包含项目源码、项目文档、数据库脚本、软件工具等资料&#xff1b;带你从零开始部署运行本套系统。2、项目介绍教学评价系统是以Java平台作为开发环境&#xff0c;采用MySQL数据库作为后台&#xff0c;使用Eclipse作为开发工具进行设计。本系统主要实现了教学评价模块、…

作者头像 李华
网站建设 2026/7/7 9:43:43

Go语言变量

Go变量声明的核心机制 静态类型语言要求变量在使用前必须声明&#xff0c;明确内存边界。Go作为静态语言&#xff0c;通过变量声明实现这一机制&#xff1a; 变量绑定特定内存区域&#xff0c;类型信息确定操作边界声明形式为&#xff1a;var 变量名 类型 值未显式初始化时自动…

作者头像 李华
网站建设 2026/7/4 21:22:52

【高可用系统架构】

系统高可用实现手段 冗余与无单点设计 部署关键节点时避免单点故障&#xff0c;例如负载均衡采用双节点Keepalived方案&#xff08;如Nginx/HAProxy/LVS&#xff09;&#xff0c;通过虚拟IP实现故障自动切换。网络通信配置多线路&#xff08;如移动电信双线&#xff09;&#x…

作者头像 李华