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