c# - 在 C# 中跨多个类传播属性更改
问题描述
我正在使用 C#、WPF 和 .NETcore3.1 来设计 GUI。这是我第一次使用 C#,所以我的项目结构可能看起来不寻常或不理想。虽然欢迎提出使代码对 C# 更友好的建议(因为我希望有一些“使用 MVVM”的答案),但这不是我在这里遇到的主要问题。
我最终得到了以下一般结构:
- 一个执行业务逻辑的 DLL 项目,大部分独立于 GUI
- 我想用来显示来自 DLL 的信息的 WPF 应用程序
就班级而言,这看起来像
- DLL 中的一个类(就这个问题而言,实际上是一组类)包含实际的业务逻辑,并且出于所有实际目的,您可以假设将异步更改。让我们称之为 BusinessLogicClass
- GUI 项目中的一个类,它创建各种表示层,本质上将 BusinessLogicClass 的相关属性重塑为可以使用绑定从 XAML 直接使用的格式。我们称之为 PresentationLayerClass。请注意,这是作为用户控件实现的。
- XAML GUI 本身。具体来说,自定义控件的 XAML GUI。
一些伪代码:
// In the DLL
class BusinessLogicClass:
public Boolean status{ get; set; }
// In the GUI
Using DLLNamespace;
public partial class PresentationLayerClass : UserControl
private BusinessLogicClass actual;
public PresentationLayerClass(BusinessLogicClass actual){
InitializeComponent();
this.DataContext = this;
this.actual = actual;
}
public string ConnectionStatus{
get{
if (this.actual.status == true) return "LanConnect";
else return "LanDisconnect";
}
}
public string StatusColor{
get {
if (this.actual.status == true) return "Green";
else return "Red";
}
}
// In the XAML
<iconPacks:PackIconMaterial Kind="{Binding ConnectionStatus}" Margin="5" Foreground="{Binding StatusColor}"/>
现在,我明白(虽然还没有弄清楚如何测试它)当 PresentationLayerClass 的属性发生变化时,GUI 将“更新自身”。
我想要的是,对 BusinessLogicClass 的状态属性的异步更改会沿链一直传播到 GUI。
如果有必要,为了简单起见并且因为我还没有足够的知识来解释更多,假设一切都在同一个线程上,并且异步的更改是由用户在 GUI 本身上触发的。说一个按钮。但是,按钮和此显示器彼此不知道也不一定不知道彼此的任何信息。信息必须通过 DLL,并且 DLL 必须触发对更新的更改。
此外,不应将 DLL 硬编码到 GUI - 我希望能够单独运行 DLL,也可以使用 CLI 应用程序或其他 GUI 运行 DLL。
我希望 INotifyPropertyChanged 的某种组合可以完成这项工作,但我似乎无法弄清楚我将如何设置它。INotifyPropertyChanged 似乎总是在 GUI 和绑定的上下文中讨论。
我知道 MVVM 应该有助于简化这类事情。虽然我有理由想在这种特殊情况下避免使用 MVVM,但我承认我还没有完全相信 MVVM 通常值得麻烦。我非常反对流行的 MVVM 库建立的明显隐式链接。我无意开始对 MVVM 进行哲学讨论,但任何希望驳斥我这个概念的人都可以把他们的情况搁置一旁——只要你明白 MVVM 不是我在这里提出的问题的主题。
解决方案
不是告诉你你已经知道什么,但是你的很多问题可能通过阅读INotifyPropertyChanged
界面来回答。
INotifyPropertyChanged
概括
通常,除非执行检查,否则没有对象知道另一个对象的属性是否已更改。这本质上是事件的目的,当某些事情发生变化时发出警报,这样其他对象就不必一直检查。但是有很多方法可以声明具有各种不同签名的事件。
INotifyPropertyChanged
提供了一个简单的基本标准,可以用来告诉其他对象什么时候发生了变化,以及什么属性发生了变化。它定义了PropertyChanged
事件,其中包括作为参数的已更改属性的名称。实现的类型INotifyPropertyChanged
负责PropertyChanged
在属性更改时显式引发事件,这通常在set
每个属性的方法中完成。
WPF 框架旨在支持该INotifyPropertyChanged
接口。WPF 数据绑定检查实现INotifyPropertyChanged
和侦听PropertyChanged
事件的对象。当这个偶数被提出时,他们会检查PropertyChangedEventArgs.PropertyName
哪个属性被改变了。如果该属性绑定到,WPF 知道更新该绑定。
在 WPF 中,还有依赖属性。这些有很多有用的功能,但最相关的是它们还实现了自己的更改通知,WPF 知道要注意这些。
您的实施
按照您PresentationLayerClass
当前定义的方式,UI不会自动更新ConnectionStatus
或StatusColor
更改。这是因为这些属性没有作为依赖属性或INotifyPropertyChanged
属性实现。当然,这两个值都取自BusinessLogicClass
,所以让我们从那里开始。
BusinessLogicClass
应该实现INotifyPropertyChanged
,并且属性应该在设置时status
引发事件。PropertyChanged
除此之外,您还需要为该事件添加一个事件处理程序PresentationLayerClass
。示例:并在构造函数(方法)
private void BusinessLogic_PropertyChanged(object sender, PropertyChangedEventArgs e)
中附加处理程序。public PresentationLayerClass
现在在该PresentationLayerClass
级别,在BusinessLogic_PropertyChanged
方法中,您必须检查哪个属性BusinessLogicClass
已更改(通过使用PropertyChangedEventArgs.PropertyName
),然后更新PresentationLayerClass
依赖于该更改的属性的任何属性的值。根据您决定使用的模式,更新依赖属性会有所不同:
PresentationLayerClass
使用依赖属性:您必须为每个依赖的依赖属性显式设置新值。PresentationLayerClass
用途INotifyPropertyChanged
:您必须PropertyChanged
为每个从属属性引发一次事件。(专业提示:使用nameof
而不是硬编码属性名称)。
推荐阅读
- r - 如何从存储在另一个数据框中的与测试记录最相似的数据集中找到记录?
- python - 如何将标准输入上的输入发送到 Makefile 中定义的 python 脚本?
- ms-access - 查询工具和设置
- javascript - require(): "不是函数"
- java - 当我单击通知中的按钮时如何更新活动 UI?
- visual-c++ - 在 C++ 中更改 MFC 菜单弹出文本
- c# - 在任务栏应用程序悬停时显示控件
- c++ - 类型定义 X
=T::UserType1,但如果不适用,typedef X =用户类型2 - mdx - MDX 格式化结果
- angular - 带有LatestFrom警告的Angular7 Ngrx6