C#将GUI与工作逻辑

时间:2017-06-07 14:17:09

标签: c# user-interface events

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

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

我猜这意味着使用事件进行通信,也可能使用Interfaces,但我对任何事情持开放态度。

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

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

我发现的大多数解决方案都会暗示要做什么,但不会掩饰 声明事件的位置以及另一个事件的具体细节 一段代码找出了事件的存在,因此它可以发出 事件或回应事件。我总是最终需要一个全局变量来将事物连接在一起。

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

我在任何地方找到的最接近的解决方案是: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;
    }
}

1 个答案:

答案 0 :(得分: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中,我们创建了侦听属性更改的处理程序,然后处理程序执行任何处理。

一个注意事项。你说

  

我想有几个消费者"看"当工作中的财产   代码更改值

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

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