C# 使用委托从另一个类调用主类函数

C# 使用委托从另一个类调用主类函数,c#,delegates,C#,Delegates,我有一个窗体和另一个类文件,当我单击主窗体中的按钮时,它将值传递给另一个文件中另一个类中的函数(该函数是通用函数,由所有文件调用),该函数再次调用主窗体/类中的函数并更新文本框 我已经编写了代码,但它抛出了一个异常:“在创建窗口句柄之前,不能对控件调用Invoke或BeginInvoke。” 代码在这里。。请纠正错误的地方。 主窗体有按钮和文本框 主要形式 另一个类文件 您需要将对Form1的引用传递到nnn(): 并从Class1类中删除Form1 theMDIform成员 目前,您从一个Fo

我有一个窗体和另一个类文件,当我单击主窗体中的按钮时,它将值传递给另一个文件中另一个类中的函数(该函数是通用函数,由所有文件调用),该函数再次调用主窗体/类中的函数并更新文本框

我已经编写了代码,但它抛出了一个异常:“在创建窗口句柄之前,不能对控件调用Invoke或BeginInvoke。”

代码在这里。。请纠正错误的地方。 主窗体有按钮和文本框

主要形式 另一个类文件
您需要将对
Form1
的引用传递到
nnn()

并从
Class1
类中删除
Form1 theMDIform
成员

目前,您从一个
Form1
对象调用
nnn()
,但随后又调用另一个不正确的
Form1
对象。您需要回调相同的
Form1
对象

添加
从其他表单调用nnn()时,还需要传递对
Form1
的引用。因此,您需要另一种形式以某种方式获取引用。一种可能的解决方案是将对
Form1
的引用存储在静态变量中。这将是Singleton模式的一个实现。我个人不喜欢这种方法,因为您可能决定在将来拥有多个
Form1
对象:

class Form1{
    private static Form1 oInstance;

    // Don't call it from the `Form1` constructor because that
    // will publish the not completely constructed object!
    private void InitInstance(){
        if (oInstance == null)
            oInstance = this;
        else
            throw new SomeException(...);
    }

    public Form1 Instance{
        get{ return oInstance;}
    }
    ...
};
然后其他表单可以获取所需的引用,如
Form1.Instance
,并将其传递给
nnn()

但我更愿意将对
Form1
对象的引用传递给每个表单,例如作为构造函数参数:

class OtherForm{
    private Form1 MainForm;

    public OtherForm(Form1 MainForm){ ...}
}
为了避免紧张,我建议不要使用诸如将表单作为参数传递(如果必须,请使用遵循原则的界面)或从表单中“请求”操作之类的命令

我的建议是,以主从方式设计程序。你的
class1
(冒充奴隶)应该做它所做的事情,并使用事件通知任何想知道它的行为的人。你的奴隶阶级不应该意识到你更高级别的主人阶级(也就是你的形态)的存在

表单将侦听事件,并将采取您认为适合所触发事件的操作

归根结底,这与你目前拥有的并没有多大的变化。主要区别在于,应该删除事件
WriteToListBoxDelegate
,而不是将
onNnn
事件添加到
class1
,并使窗体侦听该事件

事件的代码可以如下所示:

public event EventHandler<StringArgs> onNnn;
public int nnn(int a)
{

    if(this.onNnn != null)
    {
        string s = "any text you want to path";
        StringArgs arg = new StringArgs(s);
        this.onNnn(this,arg);
    }
    return 0;
}
并在您的表单中向事件添加绑定:

public Form1()
{
    InitializeComponent();
    class1Instance.onNnnn += this.HandleClass1Nnn;

}

private voit HandleClass1Nnn(object sender, StringArgs args)
{
     textBox1.Text += args.Txt;
}

如果我直接从另一个类从main函数调用函数并更新文本框,当类函数中的函数控件移回main窗体时,文本框将丢失数据。如果您指出错误的位置,那就太好了……错误将抛出到第行:theMDIform.Invoke(new Form1.WriteToListBoxDelegate(theMDIform.SetListBox),“1”);这看起来像是危险的递归。它看起来也像是您试图在一个尚不存在的窗口上执行一个函数。您知道,就像错误所说的那样?您还有一个循环依赖关系。我建议您重新审视您是如何组织代码的。即使这个错误现在已为您解决,以后您也会遇到更大的问题re,更大的问题。如果这个nnn是从另一个表单调用的,比如说Form2。那么它看起来是这样的:Form2->nnn->Form1,那么nnn的签名会改变。不是吗?@johnsonpinto我在我的答案中添加了这个问题的解。this.onNnn(this,theMDIform.SetListBox);表示'Delegate'System.EventHandler'有一些无效参数',例如ClassInstance.onNnnn+=this.HandleClass1Nnn;表示'Class1不包含onNnn'StringArgs arg=new StringArgs的定义(theMDIform.SetListBox);表示“参数“1”的最佳重载方法匹配”:无法将函数“nnn”@johnsonpin中Class1中的上述错误行从“方法组”转换为“字符串”,请重试。没有错误,但Class1中的“this.onNnn”始终为空,因此不更新Form1中的文本框。
class OtherForm{
    private Form1 MainForm;

    public OtherForm(Form1 MainForm){ ...}
}
public event EventHandler<StringArgs> onNnn;
public int nnn(int a)
{

    if(this.onNnn != null)
    {
        string s = "any text you want to path";
        StringArgs arg = new StringArgs(s);
        this.onNnn(this,arg);
    }
    return 0;
}
public class StringArgs : EventArgs
{
    private readonly string _txt;
    public string Txt
    {
        get { return this._txt; }
    }

    public StringArgs (string txt)
    {
        this._txt = txt;
    }   
}
public Form1()
{
    InitializeComponent();
    class1Instance.onNnnn += this.HandleClass1Nnn;

}

private voit HandleClass1Nnn(object sender, StringArgs args)
{
     textBox1.Text += args.Txt;
}