WPF学习PropertyChanged

让我解释一下 `PropertyChanged` 事件的订阅过程。在 WPF 中,当我们使用数据绑定时,WPF 框架会自动订阅 `PropertyChanged` 事件。让我们看看完整的流程:

  1. **事件声明**:

```csharp

public event PropertyChangedEventHandler? PropertyChanged;

```

  1. **事件触发**:

在您的 `MainViewModel` 中,当属性值改变时,通过 `OnPropertyChanged` 方法触发事件:

```csharp

protected virtual void OnPropertyChanged(string propertyName)

{

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

}

```

  1. **实际订阅发生在 XAML 绑定时**:

```xml

<Window.DataContext>

<viewmodels:MainViewModel/>

</Window.DataContext>

<TextBlock Text="{Binding Message}"

FontSize="24"

Margin="0,0,0,20"/>

```

当 XAML 中使用 `Binding` 时,WPF 框架会:

  1. 创建一个 `BindingExpression` 对象

  2. 这个对象会自动订阅目标对象(ViewModel)的 `PropertyChanged` 事件

  3. 当事件触发时,更新 UI 元素

让我们通过一个具体例子来说明:

```csharp

public class MainViewModel : INotifyPropertyChanged

{

private string _message = "Hello World";

// 属性

public string Message

{

get => _message;

set

{

if (_message != value)

{

_message = value;

// 当值改变时,触发PropertyChanged事件

OnPropertyChanged(nameof(Message));

}

}

}

// 事件声明

public event PropertyChangedEventHandler? PropertyChanged;

// 触发事件的方法

protected virtual void OnPropertyChanged(string propertyName)

{

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

}

}

```

当这个 ViewModel 被设置为 Window 的 DataContext 时:

```xml

<TextBlock Text="{Binding Message}"/>

```

WPF 内部会执行类似这样的操作(这是简化的示意,实际实现更复杂):

```csharp

// WPF框架内部的绑定处理(简化版)

var viewModel = (MainViewModel)DataContext;

viewModel.PropertyChanged += (sender, args) =>

{

if (args.PropertyName == "Message")

{

// 更新UI元素的值

textBlock.Text = viewModel.Message;

}

};

```

所以,虽然在代码中我们没有看到显式的订阅,但是:

  1. WPF 的绑定系统会自动处理订阅

  2. 每个绑定到 ViewModel 属性的 UI 元素都会创建一个订阅

  3. 当我们调用 `OnPropertyChanged` 时,所有订阅的 UI 元素都会收到通知并更新

这就是为什么我们只需要:

  1. 实现 `INotifyPropertyChanged` 接口

  2. 声明 `PropertyChanged` 事件

  3. 在属性变化时调用 `OnPropertyChanged`

WPF 框架会处理剩下的所有事情,包括事件订阅和 UI 更新。这是 WPF 数据绑定系统的一个重要特性,它使得 MVVM 模式的实现变得更加简单和优雅。

相关推荐
wuty0079 小时前
WPF 调用 Win32的SetWindowDisplayAffinity 函数 实现捕获屏幕时,过滤指定的窗口
wpf·setwindowdisplayaffinity·过滤窗口·wgc·截屏过滤窗口
TracyCoder12310 小时前
RocketMQ技术原理简单解析:从架构到核心流程
架构·wpf·rocketmq
烽火聊员11 小时前
SSLSocket 服务器端WPF C#测试代码
开发语言·c#·wpf·ssl
暮雪倾风12 小时前
【WPF开发】加载solidworks的3D模型
wpf
Macbethad12 小时前
高性能 CANopen 主站程序技术方案 (基于 WPF)
网络协议·wpf·信息与通信
Macbethad1 天前
使用WPF编写一个工控软件设置界面
wpf
wuli_滔滔1 天前
【探索实战】深入浅出:使用Kurator Fleet实现跨云集群的统一应用分发
架构·wpf·kurator·fleet
松☆1 天前
Flutter 与 OpenHarmony 深度集成:自定义 MethodChannel 插件开发全指南
flutter·wpf
Aevget1 天前
界面控件DevExpress WPF中文教程:Data Grid - 虚拟源限制
hadoop·wpf·界面控件·devexpress·ui开发
听风吟丶1 天前
Java 微服务日志实战:ELK+SkyWalking 构建全链路日志监控与智能告警体系某电商平台曾因日志问题陷入
wpf