C# - 在一个父窗体调用函数(C# - Call a function in a parent f

2019-10-18 04:40发布

我想打电话从其他形式的主要形式的函数...已得到调用一个简单的函数,通过宣布在主要形式,它的公共静态的,但我不能把所需要的一个。 要调用的函数:

    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#的,但因为它经常发生,我只是做了我的工作,所以我希望得到帮助,如果碰巧我没有得到我自己的解决方案。 谢谢 :)

Answer 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,以便下一次我们点击一​​个新的形式打开,因为关闭时老被人布置的按钮。

最好的问候汉斯铣...



Answer 2:

不能引用控件实例对你MainForm在一个静态方法。 像编译器告诉你,你需要以更新的东西像文本框形式的一个实例。 如果没有一个实例,在那里你会尝试的值更新去?

我不知道究竟是如何被创建子形式,但你可以调用你的方法中的一种方式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();
}


Answer 3:

您不能访问非静态成员在静态情况下,这意味着你必须做静态txtSendKeys,或者使你的函数的非静态的。



Answer 4:

如果您创建一个静态函数,你可能不引用不是静态的,以及在函数内部全局变量。

因此,为了使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同样的问题。

你可以改变它取一个boolean参数。

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

    }


Answer 5:

你可以把共享代码中的第三类就是以这两种形式显示。 因此,举例来说:

public class static HelperFunctions
{

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

然后更换

MainForm.spotcall()

HelperFunctions.spotcall()


Answer 6:

MainForm就是一个类。 它具有类的结构。 但是你可以从它那里得到的唯一数据是static数据。

但是,一个instance ,当你这样做类的出现: MainForm MyFormInstance = new MainForm();

MainForm只能用于访问静态成员(方法,属性...)。 当你想要得到的txtSendKeys ,你必须从一个实例(对象引用)得到它。 这是因为文本框是不是静态的,因此它只在窗体的情况存在。

所以,你应该做到以下几点:

  • spotcall不是一成不变的。
  • 放入孩子形成一个可变MainForm MyParentMainForm;
  • 当你调用子,设置MyParentMainForm与MainForm的实例。 如果它被从主窗体调用,您可以用获取实例this关键字。
  • 内部子窗体,调用MyParentMainForm.spotcall

PS:我不知道是否有像一个真正的孩子形式,或者如果你只是从另一个调用新的形式。 如果有一个真正的child形式,你可以得到Parent属性来访问主窗体的实例。



Answer 7:

这是不大不小的“设计模式”的问题,我将阐述的,但我可以试着解释最直接的方式来解决这个问题,如果你不希望这个程序发生很大的变化。 “静态”的东西只存在一次 -一次是在整个应用程序。 当一个变量或函数是静态的,它是从程序中的任何地方访问要容易得多; 但你不能访问对象的相关数据,因为你不是指向该对象的特定实例(例如,你有七个MainForms。哪一个是你调用这个函数呢?)因为标准的WinForm设计希望你可以有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类控制只为你想一个简单的事情。 随着代码变得越来越复杂,你开始发现一些事情会更有意义,移动到类“分段”不与用户(所以,有一天交互,如果这是重新编码为一个服务器程序,你可以扔掉的表单类,并且只使用逻辑类 - 从理论上讲)。 它也需要一定的时间让很多程序员了解对象的整体概念“实例”和“上下文”,一个功能要求收回。



文章来源: C# - Call a function in a parent form
标签: c# forms