首页 > 解决方案 > 在 C# 中跨多个类传播属性更改

问题描述

我正在使用 C#、WPF 和 .NETcore3.1 来设计 GUI。这是我第一次使用 C#,所以我的项目结构可能看起来不寻常或不理想。虽然欢迎提出使代码对 C# 更友好的建议(因为我希望有一些“使用 MVVM”的答案),但这不是我在这里遇到的主要问题。

我最终得到了以下一般结构:

  1. 一个执行业务逻辑的 DLL 项目,大部分独立于 GUI
  2. 我想用来显示来自 DLL 的信息的 WPF 应用程序

就班级而言,这看起来像

  1. DLL 中的一个类(就这个问题而言,实际上是一组类)包含实际的业务逻辑,并且出于所有实际目的,您可以假设将异步更改。让我们称之为 BusinessLogicClass
  2. GUI 项目中的一个类,它创建各种表示层,本质上将 BusinessLogicClass 的相关属性重塑为可以使用绑定从 XAML 直接使用的格式。我们称之为 PresentationLayerClass。请注意,这是作为用户控件实现的。
  3. 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 不是我在这里提出的问题的主题。

标签: c#wpfinotifypropertychanged

解决方案


不是告诉你你已经知道什么,但是你的很多问题可能通过阅读INotifyPropertyChanged界面来回答。


INotifyPropertyChanged概括

通常,除非执行检查,否则没有对象知道另一个对象的属性是否已更改。这本质上是事件的目的,当某些事情发生变化时发出警报,这样其他对象就不必一直检查。但是有很多方法可以声明具有各种不同签名的事件。

INotifyPropertyChanged提供了一个简单的基本标准,可以用来告诉其他对象什么时候发生了变化,以及什么属性发生了变化。它定义了PropertyChanged事件,其中包括作为参数的已更改属性的名称。实现的类型INotifyPropertyChanged负责PropertyChanged在属性更改时显式引发事件,这通常在set每个属性的方法中完成。

WPF 框架旨在支持该INotifyPropertyChanged接口。WPF 数据绑定检查实现INotifyPropertyChanged和侦听PropertyChanged事件的对象。当这个偶数被提出时,他们会检查PropertyChangedEventArgs.PropertyName哪个属性被改变了。如果该属性绑定到,WPF 知道更新该绑定。

在 WPF 中,还有依赖属性。这些有很多有用的功能,但最相关的是它们还实现了自己的更改通知,WPF 知道要注意这些。


您的实施

按照您PresentationLayerClass当前定义的方式,UI不会自动更新ConnectionStatusStatusColor更改。这是因为这些属性没有作为依赖属性或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而不是硬编码属性名称)。

推荐阅读