我正在尝试从另一种形式调用主窗体中的函数...已经调用了一个简单的函数,通过在主窗体中声明它是public static,但我无法调用所需的函数。 要调用的函数:
public static void spotcall()
{
string dial = Registry.CurrentUser.OpenSubKey("SOFTWARE").OpenSubKey("INTERCOMCS").GetValue("DIAL").ToString();
MainForm.txtSendKeys.Text = dial;// Here it asks me for a reference to an object.
foreach (char c in txtSendKeys.Text)
{
sideapp.Keyboard.SendKey(c.ToString(), checkBoxPrivate.Checked);
}
txtSendKeys.Clear();
}
我用来从子表单调用它的过程:
private void button1_Click(object sender, EventArgs e)
{
button1.Text = "Hoho";
MainForm.spotcall();
}
我完全承认我缺乏一些关于C#的理论,但是因为它经常发生,我只需要为我的工作做,所以我希望得到帮助,如果我偶然得不到自己的解决方案。谢谢:))
答案 0 :(得分:5)
您无法在静态方法中引用MainForm
上的控件实例。就像编译器告诉你的那样,你需要一个表单实例来更新TextBoxes之类的东西。如果没有实例,您尝试更新的值会在哪里?
我不确定如何创建子表单,但是您可以在MainForm
上调用方法的一种方法是直接向子表单提供MainForm
实例的引用。这可能是通过构造函数或一些公共财产。
例如
public class ChildForm : Form {
public MainForm MyParent { get; set; }
private void button1_Click(object sender, EventArgs e)
{
button1.Text = "Hoho";
// Now your child can access the instance of MainForm directly
this.MyParent.spotcall();
}
}
假设您在ChildForm
内创建MainForm
代码,为孩子提供参考非常简单:
var childForm = new ChildForm();
childForm.MyParent = this; // this is a `MainForm` in this case
childForm.Show();
您还需要使spotcall
成为实例方法,而不是静态方法,并删除代码中MainForm
的静态引用:
public void spotcall()
{
string dial = Registry.CurrentUser.OpenSubKey("SOFTWARE").OpenSubKey("INTERCOMCS").GetValue("DIAL").ToString();
// Now it no longer asks you for a reference, you have one!
txtSendKeys.Text = dial;
foreach (char c in txtSendKeys.Text)
{
sideapp.Keyboard.SendKey(c.ToString(), checkBoxPrivate.Checked);
}
txtSendKeys.Clear();
}
答案 1 :(得分:2)
您无法在静态上下文中访问非静态成员,这意味着您必须使txtSendKeys保持静态,或使您的函数保持非静态。
答案 2 :(得分:1)
如果创建静态函数,则可能不会在函数内引用非静态函数的全局变量。
因此,为了使spotcall成为静态,你必须删除对txtSendKeys的引用(我假设这是你在表单中其他地方创建的文本框)或者必须在静态函数中声明txtSendKeys。
其他:
您通过变量拨号获取了上一行中txtSendKeys.Text的值。根本没有引用txtSendKeys.Text,我想你可以简单地使用变量拨号来完成这个功能并让函数保持静态(无论如何你都要清除它)。
public static void spotcall()
{
string dial = Registry.CurrentUser.OpenSubKey("SOFTWARE").OpenSubKey("INTERCOMCS").GetValue("DIAL").ToString();
foreach (char c in dial)
{
sideapp.Keyboard.SendKey(c.ToString(), checkBoxPrivate.Checked);
}
}
虽然这不会克服同样的问题,但您可能会遇到checkBoxPrivate.Checked。
您可以将其更改为采用布尔参数。
public static void spotcall(Boolean PrivateChecked)
{
string dial = Registry.CurrentUser.OpenSubKey("SOFTWARE").OpenSubKey("INTERCOMCS").GetValue("DIAL").ToString();
foreach (char c in dial)
{
sideapp.Keyboard.SendKey(c.ToString(), PrivateChecked);
}
}
答案 3 :(得分:1)
我认为正确的方法是使用委托。这样,您的表单(窗口)不必知道任何有关父表单的信息(表单可以从不同的父表单打开)。
我们想要在子窗体关闭时调用父窗体中的函数(不要将窗体显示为模态)。
在您的子表单顶部创建一个委托:
public delegate void CloseEvent();
public CloseEvent WindowClosed;
创建表单结束事件并让它调用您的委托:
private void child_FormClosing(object sender, FormClosingEventArgs e)
{
WindowClosed();
}
父表单中的按钮可以显示子表单并设置回调:
private ChildForm childform = null;
private void buttonShowChildForm_Click(object sender, EventArgs e)
{
if (childform == null)
{
childform = new ChildForm();
childform.WindowClosed += childClosed;
childform.Show();
} else
{
childform.BringToFront();
}
}
private void childClosed()
{
childform = null;
}
在此示例中,我们使用按钮打开不阻止父窗体的新窗体。如果用户第二次尝试打开表单,我们只需将现有表单放到前面即可向用户显示。当表单关闭时,我们将对象设置为null,以便下次单击按钮时打开一个新表单,因为旧表单在关闭时处理。
祝你好运 汉斯米林......
答案 4 :(得分:0)
您可以将共享代码放在两个表单都可见的第三个类中。所以,例如:
public class static HelperFunctions
{
public static void spotcall()
{
. . .
}
}
然后替换
MainForm.spotcall()
带
HelperFunctions.spotcall()
答案 5 :(得分:0)
MainForm
只是一个类。它具有类的结构。但是,您可以从中获得的唯一数据是static
数据。
但是当您执行以下操作时,会显示该类的instance
:MainForm MyFormInstance = new MainForm();
MainForm
只能用于访问静态成员(方法,属性......)。
如果要获取txtSendKeys
,则必须从实例(对象引用)获取它。那是因为文本框不是静态的,所以它只存在于表单的实例中。
因此,您应该执行以下操作:
spotcall
不是静态的。MainForm MyParentMainForm;
this
关键字获取实例。MyParentMainForm.spotcall
PS:我不确定是否有类似真正的儿童形式,或者你只是从另一个人那里打电话给新形式。如果确实有child
表单,您可以获取Parent
属性来访问主表单的实例。
答案 6 :(得分:0)
这是一种“设计模式”问题,我将详细说明,但如果您不希望此程序发生很大变化,我可以尝试解释解决此问题的最直接方法。 “静态”事物只存在一次 - 一次在整个应用程序中。当变量或函数是静态的时,从程序中的任何地方访问都会容易得多;但是你无法访问对象的相关数据,因为你没有指向该对象的特定实例(即,你有七个MainForms。你在调用这个函数是哪一个?)因为标准的WinForm设计需要你可以拥有显示7个MainForm副本,所有相关的变量将是实例变量或非静态变量。但是,如果您希望永远不会有第二个MainForm,那么您可以采用“单例”方法,并且可以轻松访问您的一个实例。
partial class MainForm {
// only including the code that I'm adding; I'm sure there's a lot of stuff in your form.
public static MainForm Instance { public get; private set; }
protected void onInitialize() { // You need to hook this part up yourself.
Instance = this;
}
}
partial class SubForm {
protected void onImportantButton() {
MainForm.Instance.doImportantThing()
}
}
在许多初学者的代码中,在表单类中放置过多的活动数据更改逻辑是一个非常常见的问题。这不是一个可怕的事情 - 你不想只是为了一个简单的事情而做5个控制课程。随着代码变得越来越复杂,你开始发现一些事情更有意义转移到不与用户交互的类的“子级”(所以,有一天,如果将其重新编码为服务器程序) ,你可以扔掉表单类,只使用逻辑类 - 理论上讲。许多程序员也需要一些时间来理解对象“实例”的整个概念,以及调用函数的“上下文”。