C#-调用父窗体中的函数

本文关键字:函数 窗体 调用 C#- | 更新日期: 2023-09-27 18:15:59

我正试图从另一个窗体调用主窗体中的函数…已经调用了一个简单的函数,通过在主窗体中声明它为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#的理论,但正如经常发生的那样,我只需要为我的工作做这件事,所以如果碰巧我不能自己找到解决方案,我希望能得到帮助。谢谢:(

C#-调用父窗体中的函数

您不能在静态方法中引用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(); 
    }   
}

假设您在MainForm中创建ChildForm,那么给孩子一个引用的代码非常简单:

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();
}

我认为正确的方法是使用委托。这样,您的窗体(窗口(就不必知道父窗体的任何信息(该窗体可以从不同的父窗体打开(。

假设我们想在子窗体关闭时调用父窗体中的函数(不将窗体显示为模态(。

在您的子窗体顶部创建一个委托:

    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,以便下次单击按钮时打开一个新窗体,因为旧窗体在关闭时已被处理。

致以最良好的问候Hans Milling。。。

如果创建一个静态函数,则可能不会在函数内引用非静态的全局变量。

因此,为了使spotcall是静态的,您必须删除对txtSendKeys的引用(我假设这是您在表单中其他地方创建的文本框(,或者txtSendKey必须在静态函数中声明。

附加:

您通过变量拨号获得了前一行中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);
        }
    }

您可以将共享代码放在对两个表单都可见的第三个类中。例如:

public class static HelperFunctions
{
    public static void spotcall()
    {
        . . . 
    }
}

然后更换

MainForm.spotcall()

带有

HelperFunctions.spotcall()

您不能在静态上下文中访问非静态成员,这意味着您必须将txtSendKeys设置为静态,或者将您的函数设置为非静态。

MainForm只是一个类。它具有类的结构。但你能从中得到的唯一数据是static数据。

但当您这样做时,会出现该类的instanceMainForm MyFormInstance = new MainForm();

MainForm只能用于访问静态成员(方法、属性…(。当您想要获取txtSendKeys时,必须从实例(对象引用(中获取它。这是因为文本框不是静态的,所以它只存在于表单的实例中

因此,您应该执行以下操作:

  • 使spotcall非静态
  • 以子形式放入变量MainForm MyParentMainForm;
  • 当您调用子级时,使用主窗体的实例设置MyParentMainForm。如果它是从主窗体调用的,则可以使用this关键字获取实例
  • 在子窗体内,调用MyParentMainForm.spotcall

附言:我不确定是否有真正的儿童表格,或者你只是从另一个表格调用新表格。如果真的有一个child表单,您可以获取Parent属性来访问主表单的实例。

这是一个"设计模式"问题,我将对此进行详细说明,但如果您不希望此程序发生太大变化,我可以尝试解释解决此问题的最直接方法。"静态"事物只存在一次-在整个应用程序中存在一次。当一个变量或函数是静态的时,从程序中的任何地方访问都会容易得多;但是你不能访问对象的关联数据,因为你没有指向该对象的特定实例(即,你有七个MainForm。你在哪个上调用这个函数。然而,如果您希望永远不会有第二个MainForm,那么您可以采用"singleton"方法,并有一种简单的方法来访问您的一个实例。

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个控制类。随着代码变得越来越复杂,你开始发现有些事情会更有意义,转移到不与用户交互的类的"子级别"(所以,有一天,如果这被重新编码为服务器程序,你可以扔掉表单类,只使用逻辑类——从理论上讲(。许多程序员还需要一些时间来理解对象"实例"的整个概念,以及在其中调用函数的"上下文"。