C# 如何在C中保持代码与GUI的解耦?

C# 如何在C中保持代码与GUI的解耦?,c#,winforms,C#,Winforms,我开发了一个C脚本,可以打开一个XLS文件,对其进行解析,并创建一个XML文件列表来验证它们。 程序的每个主要步骤都记录如下: Console.WriteLine("Step Creating Xml 1... DONE!) Console.WriteLine("Step Validating Xml 1... DONE!) XLS文件路径目前是硬编码的,我正在用Windows窗体创建一个小型GUI,允许用户选择XLS文件并在文本框中读取程序所做的步骤 我在创建打开文件对话框以选择XSL文件的

我开发了一个C脚本,可以打开一个XLS文件,对其进行解析,并创建一个XML文件列表来验证它们。 程序的每个主要步骤都记录如下:

Console.WriteLine("Step Creating Xml 1... DONE!)
Console.WriteLine("Step Validating Xml 1... DONE!)
XLS文件路径目前是硬编码的,我正在用Windows窗体创建一个小型GUI,允许用户选择XLS文件并在文本框中读取程序所做的步骤

我在创建打开文件对话框以选择XSL文件的按钮时没有遇到任何问题,但是,一旦选中,我就对如何编写部件代码以向用户显示程序的步骤信息感到困惑

保持核心程序GUI不可知,哪种方法是完成此任务的最常用方法?

而不是编写Console.WriteLine日志记录时,只需在GUI响应的对象上引发事件:

public delegate void LogDelegate(String _data);
public class Logger
{
    public event LogDelegate OnLog;

    public void Log(String _data)
    {
        if(OnLog != null)
            OnLog(_data);
    }
}

然后,无论你的应用程序在哪里运行Console.WriteLine,它都会简单地调用该类上的Log方法。您的GUI连接到OnLog事件并执行它想要的操作。

我会在表单类中创建一个私有方法,称为WriteLog或WriteOutMessage,在该方法中,我会触摸UI,例如在多行文本框中添加一行新文本。这样,如果将来要使用另一个控件来显示输出,如网格或listview,则只需更改1个方法。

如其他答案中所述,引发GUI处理的事件以显示日志文本。 这是一个完整的示例:

1首先考虑事件中包含哪些信息,并扩展EventArgs类以定义参数事件类。我想公开一个作为日志文本的字符串:

public class LogEventArgs : EventArgs
{
    public string messageEvent {get;set;}
}        
2对于semplicity,假设您的MyApplication类公开了您想要记录的业务方法。我们将在此定义并引发一个事件。日志记录将是引发日志事件的私有方法

public class MyApplication
{
    public void BusinessMethod(){
        this.Logging("first");
        System.Threading.Thread.Sleep(1000);
        this.Logging("second");
        System.Threading.Thread.Sleep(3000);
        this.Logging("third");
     }
}
3执行事件提升。对于处理事件,我们使用一个委托,它既是对必须在接收方GUI中实现什么方法声明才能使用事件的描述,也是指向接收方方法的指针。我们将事件声明为OnLogging。 在Logging方法中,我们使用log消息引发事件设置参数。我们必须检查NOTNULL事件处理程序,因为如果没有该事件的侦听器,则该处理程序将是指向接收器事件使用者方法的null指针

    public delegate void OnLoggingEventHandler(object sender, LogEventArgs e);
    public event OnLoggingEventHandler OnLogging;

    private void Logging(string message)
    {
        LogEventArgs logMessage = new LogEventArgs();
        logMessage.messageEvent = message;
        if (OnLogging != null)
        {
            OnLogging(this, logMessage);
        }
    }
4现在我们必须实现事件的侦听器和使用它的方法。假设有一个windows窗体,其中有一个启动应用程序业务方法的按钮和一个显示日志消息的文本框。这是没有事件侦听器和使用者的表单

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

    private void button1_Click(object sender, EventArgs e)
    {
        MyApplication myApp = new MyApplication();
        myApp.BusinessMethod();
    }
}
private void button1_Click(object sender, EventArgs e)
    {
        MyApplication myApp = new MyApplication();

        myApp.OnLogging += new MyApplication.OnLoggingEventHandler(MyApplication_OnLogging);
        myApp.BusinessMethod();
    }
5我们定义了一个使用者方法,用于处理在文本框中写入事件所引发的日志消息的事件。当然,该方法具有与委托相同的签名

private void MyApplication_OnLogging(object sender, LogEventArgs e)
{
    this.textBox1.AppendText(e.messageEvent + "\n");
}
6使用C原生运算符,我们将OnLogging事件绑定到事件使用者

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

    private void button1_Click(object sender, EventArgs e)
    {
        MyApplication myApp = new MyApplication();
        myApp.BusinessMethod();
    }
}
private void button1_Click(object sender, EventArgs e)
    {
        MyApplication myApp = new MyApplication();

        myApp.OnLogging += new MyApplication.OnLoggingEventHandler(MyApplication_OnLogging);
        myApp.BusinessMethod();
    }

这正是OP不想要的,保持核心程序GUI的不可知性是的,但我提到的方法将在form1.cs中。例如,很明显,至少UI应该知道使用什么控件来显示消息。如果他有一些业务经理或核心类,他们不会知道,但表单必须知道。谢谢,LogDelegate做什么以及OnLog事件在哪里声明?@SystemPuntoot,log delegate就是事件的类型。OnLog事件在该记录器类中声明。您的代码将创建该类的实例并将其公开。您的GUI代码将向OnLog事件添加一个处理程序,并相应地进行处理;您忘了将LogDelegate添加到事件中;如果处理程序!=空处理程序_数据@Stormenet,谢谢你,我没注意到@考特尼-为什么?