【问题标题】:C# Separate GUI from Work logicC# 将 GUI 与工作逻辑分离
【发布时间】:2017-06-07 14:17:09
【问题描述】:

我想了解如何分离我的 GUI 和工作代码。 下面的人为示例代码是最小的起点, 我能想到这涵盖了这个想法。

该示例使用 Windows 窗体作为命令源和显示 (消费者)的结果。我希望工作代码能够从命令行界面获取命令。工作代码不应依赖于对表格的了解。表单应该对工作代码知之甚少。当工作代码中的属性更改值时,我希望有几个消费者“看到”。

我猜这意味着使用事件进行通信,也许还有接口,但我对任何事情都持开放态度。

那里有一百万种不同的建议。我已经阅读了设计模式书籍,并且尝试了很多,但还没有找到一个解释得很好的集合,我可以完全实现它。

我不想要一个通用的解决方案。我想要一个尽可能简单的 为小型个人项目实施和维护。我不是 为大型公司设计。

我发现的大多数解决方案都会提示该怎么做,但不会涵盖 诸如声明事件的位置以及其他事件的具体情况 一段代码找出事件的存在,因此它可以发出 事件或响应事件。我总是在某个地方最终需要一个相当于全局变量的东西来将事物连接在一起。

在这里,我能找到的与我的问题最接近的匹配是:C# Windows Forms App: Separate GUI from Business Logic 但该解决方案使用表单来创建工作者的实例并直接返回一个值,而不是通知任何感兴趣的观察者。提供的解决方案将这两个类紧密绑定。

我在任何地方找到的最接近的解决方案是:https://www.codeproject.com/Articles/14660/WinForms-Model-View-Presenter 在接口和反射方面确实有一些真的很酷,但似乎不太可维护也不太灵活。

下面源代码中的注释行显示了所需的交互 点,但没有实现。

文件#1:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // tell an instance of JustCounts to increment by 10
    }

    // Here, allow JustCounts to cause a call to this (or something
    // similar, perhaps a property) to inform this code that the TotalCount
    // property has changed.
    public void ShowNewTotalCount(int NewTotal)
    {
        Console.WriteLine("New Total Count = {0}", NewTotal);
    }
}

文件 #2

class JustCounts
{
    private int m_TotalCount = 100;
    // Inform other classes when the following property changes value,
    // preferably including the value in the notification.
    public int TotalCount { get => m_TotalCount; }

    // The code in File #1 needs to result in a call to this method
    // along with the correct argument value.
    public void AddThisMuch(int increment)
    {
        m_TotalCount += increment;
    }
}

【问题讨论】:

    标签: c# user-interface events


    【解决方案1】:

    我基于当前版本的 .Net (4.6.2)。

    如果我们实现INotifyPropertyChanged,那么我们就有了一个可以监听属性变化的事件。有点像监听按键,我们可以过滤出我们想要的特定属性。

    public class JustCounts : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        private int m_totalCount = 100;
    
        public int TotalCount
        {
            get { return m_totalCount; }
            set
            {
                if (value != m_totalCount)
                {
                    m_totalCount = value;
                    NotifyPropertyChanged();
                }
            }
        }
    }
    

    当我们公开 TotalCount 属性时,无需创建方法来操作它。

    public class Form1 : Form
    {
        // justCounts is a reference to the object wherever it is coming from
        justCounts.PropertyChanged += new PropertyChangedEventHandler(JustCountsChangedHandler);
    
    
        private void JustCountsChangedHandler(object sender, PropertyChangingEventArgs e)
        {
            // process on event firing
            Debug.WriteLine($"justCounts TotalCount changed value to {justCounts.TotalCount}");
        }
    
        // Example of where the handler will fire when called
        private void button1_click(object sender, EventArgs e)
        {
            justCounts.TotalCount++;
        }
    }
    

    在上面的代码中,我们在JustCounts 中创建了一个监听器可以订阅的事件。

    使用INotifyPropertyChanged 接口,我们在每次TotalCount 更改时触发事件。

    在表格 1 中,我们创建处理程序来侦听属性更改,然后处理程序执行任何处理。

    一个音符。你说

    我想让几个消费者“看到”房产在工作中的时间 代码改变值

    所以为了让它工作,我们必须假设工作代码可以独立于它的订阅者(类似于服务器)运行。否则,我们将为不同的订阅者提供不同的实例。

    您还提到了接口,它们可以使用但在这种情况下不是必需的。

    【讨论】:

      猜你喜欢
      • 2015-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      • 1970-01-01
      相关资源
      最近更新 更多