c# 学习笔记 PropertyChangedEventHandler、 =>、DependencyObject、DataContext

在C#中,PropertyChangedEventHandlerPropertyChanged 常常与 INotifyPropertyChanged 接口一起使用,这是实现数据绑定和通知机制的关键部分,尤其在WPF (Windows Presentation Foundation) 或其他支持数据绑定的UI框架中。

PropertyChangedEventHandler

PropertyChangedEventHandler 是一个委托,它定义了当属性发生变化时应该调用的方法的签名。这个委托接受两个参数:发送更改通知的对象(通常是实现 INotifyPropertyChanged 接口的对象)和一个 PropertyChangedEventArgs 对象,后者包含关于更改的具体信息(即哪个属性发生了变化)。

PropertyChanged 事件

PropertyChanged 是一个事件,通常在一个实现了 INotifyPropertyChanged 接口的类中声明。当类的某个属性值发生变化时,类的实现者会触发这个事件,以通知任何订阅了这个事件的监听器。

示例

下面是一个简单的例子,展示了如何在C#中实现 INotifyPropertyChanged 接口,并使用 PropertyChangedEventHandlerPropertyChanged 事件:

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;public class Person : INotifyPropertyChanged
{private string _name;private int _age;public string Name{get { return _name; }set{if (_name == value) return;_name = value;OnPropertyChanged();}}public int Age{get { return _age; }set{if (_age == value) return;_age = value;OnPropertyChanged();}}public event PropertyChangedEventHandler PropertyChanged;// 这个方法用于触发 PropertyChanged 事件protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}
}

在这个例子中,Person 类实现了 INotifyPropertyChanged 接口,并声明了 PropertyChanged 事件。NameAge 属性在它们的setter中包含了调用 OnPropertyChanged 方法的逻辑。当这些属性的值发生变化时,OnPropertyChanged 方法会被调用,并触发 PropertyChanged 事件。

[CallerMemberName] 是一个特性,它允许你在没有显式传递属性名的情况下获取当前成员的名称。这使得代码更简洁,减少了错误的可能性。

任何订阅了 Person 对象的 PropertyChanged 事件的监听器现在都会收到通知,包括哪个属性发生了变化。这通常用于UI更新,或者任何需要响应数据变化的其他逻辑。

=>

在C#中,=> 是一个特殊的符号,它主要在两种上下文中有特殊的意义:

Lambda 表达式:
Lambda 表达式是一种简洁的编写匿名函数的方法。=> 符号用于分隔输入参数和表达式体。以下是一个Lambda表达式的例子:

csharp
Func<int, int, int> add = (x, y) => x + y;
在这个例子中,(x, y) 是输入参数,而 x + y 是表达式体。

如果Lambda表达式只有一个参数,你可以省略括号:

csharp
Func<int, bool> isPositive = x => x > 0;
表达式体成员(Expression-bodied members):
从C# 6.0开始,你可以使用 => 来定义一个只有表达式体的成员(如方法、属性、索引器、构造函数和析构函数)。这可以使得代码更加简洁。

例如,一个只有表达式体的方法:

csharp
public int Square(int x) => x * x;
一个只有表达式体的只读属性:

csharp
public int Length => someList.Count;
一个只有表达式体的索引器:

csharp
public int this[int index] => data[index];
在这两种情况下,=> 都起到了分隔左侧的定义(如参数列表、属性名或索引器签名)和右侧的表达式体的作用。

WPF DependencyObject

在WPF(Windows Presentation Foundation)中,DependencyObject 是一个基础类,用于实现依赖属性(Dependency Properties)系统。依赖属性是WPF中用于数据绑定、样式、动画和默认值的强大系统。

DependencyObject 类提供了存储和检索依赖属性值的机制。与传统的.NET属性不同,依赖属性可以参与WPF的属性系统,该系统提供了许多高级功能,如数据绑定、样式、动画、值继承、默认值等。

以下是关于 DependencyObject 的一些关键点:

基础类:所有具有依赖属性的WPF类(如 Control、FrameworkElement、Shape 等)都继承自 DependencyObject。
依赖属性存储:依赖属性的值不直接存储在类的字段中,而是存储在 DependencyObject 的内部字典中。这使得WPF能够在运行时高效地查询和修改这些值。
元数据:每个依赖属性都与一个 PropertyMetadata 对象相关联,该对象包含有关该属性的元数据,如默认值、属性更改回调等。
属性更改通知:当依赖属性的值更改时,WPF可以触发各种事件和回调,如 PropertyChangedCallback。
数据绑定:依赖属性是WPF数据绑定系统的核心。通过依赖属性,你可以将UI元素与数据源进行双向绑定。
动画和渐变:WPF的动画系统使用依赖属性来驱动动画和渐变效果。
样式和模板:依赖属性允许WPF样式和模板系统通过统一的方式修改多个UI元素的外观和行为。
要使用依赖属性,你需要定义一个 DependencyProperty 静态字段,并使用 DependencyProperty.Register 方法或 DependencyProperty.RegisterAttached 方法(对于附加属性)进行注册。然后,你可以使用 GetValue 和 SetValue 方法来读取和设置依赖属性的值。

下面是一个简单的示例,展示了如何定义一个依赖属性:

csharp
public class MyControl : Control
{
// 依赖属性注册
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register(“MyProperty”, typeof(string), typeof(MyControl), new PropertyMetadata(string.Empty));

// .NET包装属性  
public string MyProperty  
{  get { return (string)GetValue(MyPropertyProperty); }  set { SetValue(MyPropertyProperty, value); }  
}  

}
在这个示例中,MyControl 类定义了一个名为 MyProperty 的依赖属性,并提供了一个相应的.NET包装属性以便于访问。

WPF DataContext

在C#的WPF(Windows Presentation Foundation)框架中,DataContext 是一个非常重要的概念,特别是在数据绑定(Data Binding)方面。DataContext 是一个对象,它包含了要绑定到UI元素(如TextBlock、ListBox、ComboBox等)的数据。这些数据可以是简单的数据类型(如string、int等),也可以是复杂的对象或集合。

DataContext 可以被设置为任何类型的对象,并且通常通过以下几种方式之一与UI元素相关联:

直接设置:你可以直接为某个UI元素(如UserControl、Window、Grid等)设置DataContext属性。这样,该元素及其所有子元素都可以访问这个DataContext中的数据。
csharp
myControl.DataContext = new MyViewModel();
继承:如果一个UI元素没有显式设置DataContext,它将从其父元素继承DataContext。这允许你在根元素(如Window或UserControl)上设置DataContext,并使其自动应用于所有子元素。
数据模板:在数据控件(如ListView、DataGrid等)中,你可以使用数据模板(Data Templates)来定义如何显示数据项。在这些模板中,你可以使用数据绑定表达式(如{Binding PropertyName})来引用当前数据项(即当前项的DataContext)的属性。
在MVVM(Model-View-ViewModel)架构中,DataContext 通常是一个ViewModel对象。ViewModel是一个充当数据中介的类,它将Model中的数据转换为适合在View中显示的形式,并处理来自View的用户输入。通过将数据绑定到ViewModel的属性,你可以轻松地将UI与数据隔离开来,从而实现更清晰的代码结构和更好的可维护性。

以下是一个简单的示例,展示了如何在WPF中设置和使用DataContext:

xml






csharp
// C# 代码
public class MyViewModel
{
public string MyProperty { get; set; } = “Hello, WPF!”;
}

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MyViewModel();
}
}
在这个示例中,我们创建了一个名为MyViewModel的类,它有一个名为MyProperty的属性。然后,在MainWindow的构造函数中,我们将MyViewModel对象设置为窗口的DataContext。最后,在XAML文件中,我们使用数据绑定表达式{Binding MyProperty}将TextBlock的Text属性绑定到MyProperty属性上。当MyProperty属性的值改变时,TextBlock的文本将自动更新以反映新的值。

c# 给出4个C1ComboBox 其中其他值也跟着变化

在C#中,如果四个C1ComboBox(第三方库如C1 Studio for .NET中的控件)中的值能够相互关联,即改变一个C1ComboBox的值会导致其他C1ComboBox的值也相应地改变,你需要实现一种事件监听机制。

以下是一个基本的步骤说明和示例代码,展示如何实现这种功能:

定义事件处理函数:为每个C1ComboBox的SelectedIndexChanged或ValueChanged事件定义一个处理函数。
更新其他控件:在事件处理函数中,根据当前C1ComboBox的选中值来更新其他C1ComboBox的值或可选项。
避免无限循环:确保在更新其他C1ComboBox时不会触发它们自己的事件,从而导致无限循环。你可以通过设置某个标志或使用BeginInvoke来在UI线程上异步更新控件来避免这个问题。
下面是一个简化的示例代码:

csharp

public partial class MyForm : Form  
{  private bool isUpdating = false; // 用于防止无限循环的标志  public MyForm()  {  InitializeComponent();  // 假设你已经有四个C1ComboBox:comboBox1, comboBox2, comboBox3, comboBox4  comboBox1.SelectedIndexChanged += ComboBox1_SelectedIndexChanged;  // 为其他三个也添加类似的事件监听  }  private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)  {  if (isUpdating) return; // 如果正在更新,则直接返回  isUpdating = true; // 设置标志,表示开始更新  try  {  // 根据comboBox1的选中值来更新其他三个ComboBox  // 例如,如果comboBox1选中了某个值,你可能想要从某个数据源中获取与该值相关的其他选项  // 并设置到comboBox2, comboBox3, comboBox4中  // 伪代码示例:  // List<string> relatedOptions = GetDataRelatedTo(comboBox1.SelectedItem);  // comboBox2.DataSource = relatedOptions;  // comboBox3.DataSource = relatedOptions; // 根据实际情况可能需要不同的数据源  // comboBox4.DataSource = relatedOptions;  // ... 实际设置代码 ...  }  finally  {  isUpdating = false; // 更新完成,重置标志  }  }  // ... 为其他三个ComboBox也添加类似的事件处理函数 ...  
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/857605.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样去掉卷子上的答案并打印

当面对试卷答案的问题时&#xff0c;一个高效而简单的方法是利用图片编辑软件中的“消除笔”功能。这种方法要求我们首先将试卷拍摄成照片&#xff0c;然后利用该功能轻松擦除答案。尽管这一方法可能需要些许时间和耐心&#xff0c;但它确实为我们提供了一个可行的解决途径。 然…

【2024.6.22】今日科技时事:科技前沿大事件

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

如何避免vue的url中使用hash符号?

目录 1. 安装 Vue Router 2. 配置 Vue Router 使用 history 模式 3. 更新 main.js 4. 配置服务器以支持 history 模式&#xff08;此处需要仔细测试&#xff09; a. Nginx 配置 b. Apache 配置 5. 部署并测试 总结 在 Vue.js 项目中&#xff0c;避免 URL 中出现 # 符号的…

docker-compose功能、操作

文章目录 前言主要功能基本用法 前言 docker-compose 是一个用于定义和运行多容器 Docker 应用的工具。它使用一个 YAML 文件&#xff08;通常命名为 docker-compose.yml&#xff09;来配置应用的服务、网络和卷等属性。通过 docker-compose&#xff0c;你可以利用一个单一的命…

YAML 入门教程

YAML 是 "YAML Aint a Markup Language"&#xff08;YAML 不是一种标记语言&#xff09;的递归缩写&#xff0c;是一种人类可读的完整的数据序列化语言。YAML 的意思其实是&#xff1a;"Yet Another Markup Language"&#xff08;仍是一种标记语言&#xf…

宝塔部署GeoServer教程

前期准备&#xff1a;下载geoserver 直接用我上传的geoserver或者是去官网下https://geoserver.org/release/stable/ 压缩包的geoserver版本是&#xff1a;2.25.1 jdk要求版本是&#xff1a;jdk11以上 tomcat版本&#xff1a;可选8或者9&#xff0c;建议用9 windows选择Window…

linux./xxx.py :Command not found

从windows传入linux系统中的py文件&#xff0c;在运行时出现了如标题所示的错误 第一行#!/bin/python3 但是却无法使用./xxx.py运行&#xff0c;通过一番调试&#xff0c;发现 windows的换行符与linux的换行符不一致导致了错误的发生 如何解决这个问题&#xff0c;使用dos2unix…

视频监控统一管理平台LntonCVS安防视频监控系统视频汇聚方案

LntonCVS平台最初被设计为一个以视频汇聚为核心的平台。那么&#xff0c;什么是视频汇聚平台&#xff0c;以及它是如何处理视频资源的呢&#xff1f;简单来说&#xff0c;视频汇聚平台能够从不同的视频源&#xff08;如直播和点播&#xff09;收集、整合和展示视频内容。以下是…

春天,快速恢复能量的10件小事(不妨试试)

春天快速恢复能量的十件小事&#xff0c;不妨试试随着天气回暖&#xff0c;万物都在恢复生机。 只是很多朋友感慨自己似乎总有些能量不足&#xff0c;没干什么重活累活&#xff0c;但觉得浑身疲乏&#xff0c;精神状态很低迷&#xff0c;不仅容易走神&#xff0c;而且记忆力也在…

Docker可视化web工具

docker run --restart always --name docker.ui -d -v /var/run/docker.sock:/var/run/docker.sock -p 8989:8999 joinsunsoft/docker.ui #--restart always&#xff1a;重启策略&#xff0c;只要关闭就会重启 http://192.168.10.51:8989 账号&#xff1a;ginghan 密码&#xf…

IOS Swift 从入门到精通: 函数,参数和异常

文章目录 编写函数接受参数返回值参数标签省略参数标签默认参数可变参数函数编写抛出函数运行异常函数输入输出参数总结 编写函数 函数让我们可以重复使用代码&#xff0c;这意味着我们可以编写一个函数来做一些有趣的事情&#xff0c;然后从很多地方运行该函数。重复代码通常…

Java匿名类

Java 匿名类是一种特殊的内部类&#xff0c;它没有名字&#xff0c;并且通常用来简化代码实现&#xff0c;尤其是在实现接口或者抽象类的实例时。匿名类可以在实例化时定义其行为&#xff0c;而不需要创建单独的类文件。 匿名类的特点 没有名字&#xff1a;匿名类是没有名字的…

写代码必用字体

下载链接 字体下载链接 使用情况/截图 软件&#xff1a;DEV-CPP 系统&#xff1a;Win10专业版 自带判等、大于、小于等符号的专属字体

计算机组成原理网课笔记2

存储系统基本概念 CPU&#xff1a;运算器控制器。​ 作为计算机系统的运算和控制核心&#xff0c;是信息处理、程序运行的最终执行单元。 ​ 主存储器的基本组成 半导体元件的原理 在电容上面的金属板加一个5V的高电平&#xff0c;产生电压差&#xff0c;电容里面的电荷就会开…

计算机系统基础实训五—CacheLab实验

实验目的与要求 1、让学生更好地应用程序性能的优化方法&#xff1b; 2、让学生更好地理解存储器层次结构在程序运行过程中所起的重要作用&#xff1b; 3、让学生更好地理解高速缓存对程序性能的影响&#xff1b; 实验原理与内容 本实验将帮助您了解缓存对C程序性能的影响…

带你学习Mybatis之MappedStatement

mybatis之MappedStatement MappedStatement是保存mapper.xml的一个节点(select|insert|delete|update)&#xff0c;包括许多配置的sql、sql的id、缓存信息、resultMap、parameterType、resultType、languageDriver等重要配置内容 public final class MappedStatement { privat…

【面向对象】复习(二)

内存对齐 class A{ static int a; } int main(){ A obj; cout<<sizeof(obj); } 在你的代码中&#xff0c;class A 包含一个静态成员变量 a。静态成员变量不属于类的任何特定实例&#xff0c;而是属于整个类。因此&#xff0c;在计算类的实例大小时&#xff0c;静态…

如何在 Ubuntu 14.04 上使用 HAProxy 实现 SSL 终止

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 HAProxy&#xff0c;全称高可用代理&#xff0c;是一款流行的开源软件 TCP/HTTP 负载均衡器和代理解决方案&#xff0c;可在 Linu…

2024.6.22 刷题总结

2024.6.22 **每日一题** 2663.字典序最小的美丽字符串&#xff0c;该题考察了回文串的性质&#xff0c;一个回文串去掉首尾字母后&#xff0c;仍然是回文串&#xff0c;可以根据这一性质得到如果没有长度为m-2的回文串&#xff0c;那么就不会有长度为m的回文串.由答案取的是最小…

OpenXlab应用部署踩坑记录

参考博客&#xff1a; OpenXlab应用部署经验_xlabdemo-web-CSDN博客 书生浦语大模型实战营Day04OpenXLab 部署_openxlab.org.cn上传模型-CSDN博客 应用创建流程 | OpenXLab浦源 - 文档中心 1、已经在OpenXlab上上传好了模型 在上传好的模型查看一下如何使用模型 2、github…