当前位置: 首页 > news >正文

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 接口

http://www.jsqmd.com/news/84644/

相关文章:

  • AI之PhoneAgent:Open-AutoGLM的简介、安装和使用方法、案例应用之详细攻略
  • 基于springboot的技术博客交流系统的设计与实现
  • LeetCode046全排列
  • day37简单的神经网络@浙大疏锦行
  • wpf 类图
  • 基于springboot的运动服服饰销售购买商城系统
  • 基于文献的‘12-文献代码复现‘:非线性模型预测控制(NMPC)多无人船USV编队控制form...
  • 【保姆级教程】爆火开源项目 Next AI Draw.io 上手指南:一句话画流程图
  • 韩语教程资源合集
  • 如何用DSPy优化RAG prompt示例
  • 英语口语资源合集
  • 鸿蒙PC UI控件库 - TextInput 文本输入框详解
  • 链表中的回文判断
  • 鸿蒙PC UI控件库 - PasswordInput 密码输入框详解
  • 【大模型预训练】07-数据处理流程设计:从原始数据到模型输入的端到端处理链路
  • 基于VMD-CPA-KELM-IOWAl-CSA-LSSVM碳排放的混合预测模型研究附Matlab代码
  • 【机器人路径规划】基于6种算法(黑翅鸢优化算法BKA、SSA、MSA、RTH、TROA、COA)求解机器人路径规划研究附Matlab代码
  • 基于6种最新算法(小龙虾优化算法COA、MSA、RTH、NOA、BFO、SWO)求解机器人路径规划研究附Matlab代码
  • 【数据结构】排序
  • 【路径规划】基于RRT快速探索随机树算法在包含圆形障碍物的环境中寻找从起点到目标点的路径附matlab代码
  • 【太阳能学报EI复现】基于粒子群优化算法的风-水电联合优化运行分析附Matlab代码
  • go构建web服务
  • 夜莺监控设计思考(三)时序库、agent 的一些设计考量
  • 系统基础服务
  • 数据结构:二叉排序树,平衡二叉树,红黑树的介绍
  • 软件测试面试题集合
  • AI中的优化5-无约束非线性规划之凸性
  • Go Module构建
  • 【time-rs】Duration 结构体详解
  • 深圳|昆明|广州|东莞-奶茶原料批发供应商|奶茶原料供应商|奶茶原料批发市场|奶茶原料批发|奶茶原料推荐|奶茶原料公司——圣旺水吧 - 老百姓的口碑