在多个 类 中传播 C# 中的 属性 更改
Propagating property changes in C# across multiple classes
我正在使用 C#、WPF 和 .NETcore3.1 设计 GUI。这是我第一次使用 C#,所以我的项目结构可能看起来不寻常或次优。虽然让代码对 C# 更友好的建议是受欢迎的(因为我希望有很多 'use MVVM' 答案),但这不是我在这里的主要问题。
我最终得到了以下一般结构:
- 一个执行业务逻辑的 DLL 项目,主要独立于 GUI
- 我想用来显示来自 DLL 的信息的 WPF 应用程序
Class-明智的,这看起来像
- DLL 中的一个 class(对于这个问题的目的,实际上是一组 classes),它包含实际的业务逻辑,并且出于所有实际目的,您可以假设将异步更改。让我们称之为 BusinessLogicClass
- GUI 项目中的一个 class,它创建了一个表示层,本质上是将 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 将 'update itself'。
我想要的是对 BusinessLogicClass 的状态 属性 的异步更改一直向上传播到 GUI。
如有必要,为了简单起见,并且因为我还没有足够的知识来解释更多,假设所有内容都在同一个线程上,并且异步更改是由用户在 GUI 本身上触发的。说一个按钮。然而,按钮和这个显示并不能也不能知道彼此的任何信息。信息必然要通过DLL,DLL必须触发变化才能更新。
此外,不应将 DLL 硬编码到 GUI - 我希望能够 运行 DLL 本身或使用 CLI 应用程序或其他 GUI。
我希望 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中,也有dependency properties。它们有很多有用的功能,但最相关的是它们还实现了自己的更改通知,WPF 知道要注意这一点。
您的实施
您当前定义 PresentationLayerClass
的方式,如果 ConnectionStatus
或 StatusColor
UI 将不会 自动更新改变。这是因为这些属性未作为依赖属性或 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
而不是硬编码 属性 名称)。
我正在使用 C#、WPF 和 .NETcore3.1 设计 GUI。这是我第一次使用 C#,所以我的项目结构可能看起来不寻常或次优。虽然让代码对 C# 更友好的建议是受欢迎的(因为我希望有很多 'use MVVM' 答案),但这不是我在这里的主要问题。
我最终得到了以下一般结构:
- 一个执行业务逻辑的 DLL 项目,主要独立于 GUI
- 我想用来显示来自 DLL 的信息的 WPF 应用程序
Class-明智的,这看起来像
- DLL 中的一个 class(对于这个问题的目的,实际上是一组 classes),它包含实际的业务逻辑,并且出于所有实际目的,您可以假设将异步更改。让我们称之为 BusinessLogicClass
- GUI 项目中的一个 class,它创建了一个表示层,本质上是将 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 将 'update itself'。
我想要的是对 BusinessLogicClass 的状态 属性 的异步更改一直向上传播到 GUI。
如有必要,为了简单起见,并且因为我还没有足够的知识来解释更多,假设所有内容都在同一个线程上,并且异步更改是由用户在 GUI 本身上触发的。说一个按钮。然而,按钮和这个显示并不能也不能知道彼此的任何信息。信息必然要通过DLL,DLL必须触发变化才能更新。
此外,不应将 DLL 硬编码到 GUI - 我希望能够 运行 DLL 本身或使用 CLI 应用程序或其他 GUI。
我希望 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中,也有dependency properties。它们有很多有用的功能,但最相关的是它们还实现了自己的更改通知,WPF 知道要注意这一点。
您的实施
您当前定义 PresentationLayerClass
的方式,如果 ConnectionStatus
或 StatusColor
UI 将不会 自动更新改变。这是因为这些属性未作为依赖属性或 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
而不是硬编码 属性 名称)。