news 2026/4/18 11:22:27

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/4/18 1:42:34

本地私有知识库新选择:访答知识库的优势与数据分析

本地私有知识库新选择&#xff1a;访答知识库的优势与数据分析 知识库市场现状概述 随着信息爆炸时代的到来&#xff0c;知识管理已成为个人和企业面临的重要挑战。根据行业数据显示&#xff0c;2023年全球知识管理市场规模已达到250亿美元&#xff0c;年增长率稳定在15%以上。…

作者头像 李华
网站建设 2026/4/18 3:25:43

ISCTF2025-病毒分析

病毒分析 注1&#xff1a;本题通过模仿某近期活跃的APT&#xff08;Advanced Presistent Threat&#xff0c;高级持续性威胁&#xff09;组织的攻击手法&#xff0c;使题目更符合真实环境&#xff0c;题目设计为不会对系统进行破坏&#xff0c;即使真机运行也不影响&#xff0…

作者头像 李华
网站建设 2026/4/17 14:13:41

基于springboot的技术博客交流系统的设计与实现

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的设计程序开发&#xff0c;开发过上千套设计程序&#xff0c;没有什么华丽的语言&#xff0c;只有实…

作者头像 李华
网站建设 2026/4/18 3:26:07

python训练营打卡day11

浙大疏锦行 知识点&#xff1a; 1.网格搜索 2.随机搜索 3.贝叶斯优化 4.time库的记时模块 5.代理模型的思想 6.给ai提问 1. 概述 核心知识点回顾 模型组成 算法 实例化设置的外参&#xff08;超参数&#xff09; 训练得到的内参 调参原则&#xff1a;只要调参就需要…

作者头像 李华
网站建设 2026/4/18 3:26:55

关于链表中元素的交换的操作

给定一个链表&#xff0c;对于每两个相邻的结点&#xff0c;交换其位置。如 1->2->3->4->null&#xff0c;返回2->1->3->4->null只能对结点进行操作&#xff0c;不能修改结点的值&#xff0c;只能操作结点&#xff08;整个&#xff09;或结点对应的指针…

作者头像 李华