在C#中从一个子窗体调用另一个子窗体

3
我有三个表单:FormA,FormB和FormC,其中FormA是mdiParent表单,而FormB和C是子表单。我在FormA的load事件中编写了以下代码。
private void frmMain_Load(object sender, EventArgs e)
{
   formB.MdiParent = this; //formB is instance of FormB             
   formC.MdiParent = this; //formC is instance of FormC
   formB.Show();      
}

我想要的是,当我在FormB上点击一个按钮时,应该显示FormC。现在,我需要在FormB中的单击事件中创建另一个FormC实例,还是可以使用在FormA中创建的实例?
如果需要创建一个单独的实例,那么有人能解释一下原因吗?
编辑- Oded给出的答案很好。但是,我能否将属性的返回类型设置为Form[],以便添加多个引用,这样如果我想从FormC返回FormB,则可以使用类似的方法?
另外,如果我想从FormB传递一些数据到FormC,该怎么做?
6个回答

2

您的FormB需要引用FormC

您可以在FromB上添加一个属性来完成这个操作:

public Form FormCRef {get;set;}

然后在你的主表单中:

formB.FormCRef = formC;

在你的 FormB 类中,在事件处理程序中执行以下操作:
FormCRef.Show();

我需要在属性FormCRef中写任何内容吗?还是应该像您写的那样保持不变? 很抱歉问这么简单的问题,但我以前从未创建过任何属性,所以对它们不太了解。 - Pratik Gandhi
+1,如果不是必需的话,我不喜欢使用表单引用,但这是一个好的解决方案。 - Amirshk
@Pratik Gandhi - 我使用的语法没问题。它被称为自动属性,是在C# 3.0中引入的。 - Oded
我现在正在使用VS2005和.Net Framework 2.0版本,这会有问题吗? - Pratik Gandhi
@Pratik Gandhi - 你需要创建一个支持字段,然后像平常一样创建属性,就是这样。 - Oded

1

你必须使用在FormA中创建的实例,因为每个表单实例代表一个不同的表单。

正确的方法是公开一个事件FormB,让FormA注册它,然后FormA可以在FormC上调用任何你想要的内容:

FormB:

// A delegate type for hooking up change notifications.
public delegate void MagicEventHandler();

public event MagicEventHandler MagicButttonClicked;    

// Invoke the event, this inside your button click event handler:
void Button1_OnClick(EventArgs e) 
{
    if (Changed != null) MagicButttonClicked();
}

FormA: // 将表单实例保存为类的私有成员,以备将来使用 FormB formB; FormB formC;

OnLoad...
{
    formB.MdiParent = this; //formB is instance of FormB             
    formC.MagicButttonClicked +=  new On_MagicButttonClicked ();
    formC.MdiParent = this; //formC is instance of FormC
    formB.Show();   
}

public void On_MagicButttonClicked()
{
    this.fromC.Activate();
}

1
在 FormA(MDIForm)中:
FormB formB = new FormB();     
formB.MdiParent = this; 
formB.Show();

在FormB中:
FormC formC = new FormC();
formC.MdiParent = (FormA)this.ParentForm;
formC.Show();
this.Close();

0

这取决于您的设计性质:

如果FormB直接与FormC交流是有意义的,那么FormB需要引用FormC。在这种情况下,我认为也许FormC不应该与FormA相关联,而是FormB应该管理FormC。(就像FormC是FormB的工具窗口)。

如果FormB直接与FormC交流没有意义,那么FormB应该向FormA“发送消息”(调用方法),然后FormA将消息发送到FormC。例如:

class FormB
{
   ...
   private void SomethingHappened()
   {
      ((FormA)MdiParent).TellFormASomethingHappened();
   }

...

class FormA
{
   private FormC mFormC;

   ...

   public void TellFormASomethingHappened()
   {
      mFormC.TellFormCSomethingHappened();
   }

...

class FormC
{
    public void TellFormCSomethingHapened()
    {
       // do something
    }
...

0
一个备选方案(可能会引起争议)是将每个表单的引用存储为静态变量。如果您只想在任何时候仅显示一个此表单实例,则此方法应该可以胜任。这被称为Singleton模式
在表单C中,添加以下内容:
private static FormC thisForm = null;

public static FormC GetFormC()
{
  if (thisForm == null)
     thisForm = new FormC();

  return thisForm;
}

public static void ShowFormC()
{
  GetFormC().Show();
}

在表格A中,如果您需要在表格C上进行任何设置,请调用:
FormC.GetFormC().mdiParent = this;

然后在表单B中,要显示表单C,请进行以下调用:

FormC.ShowFormC();

这是一个干净、清晰的代码,如果你绝对确定只需要显示一个FormC实例(这也是你的代码似乎在做的事情),那么这是逻辑上正确的方式!


0
为了减少耦合,最佳实践是使用MessageBroker/EventBroker/EventAggregator模式。您可以在这里这里找到实现。 用法: 声明事件类:
public class ShowFormCEvent {}

在FormA中订阅事件:

EventPublisher.Register<ShowFormCEvent>(e=>formC.Show());

在FormB中触发事件

EventPublisher.Publish(new ShowFormCEvent());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接