隐藏主窗体,启动新窗体,并在不关闭第二个窗体的情况下在两者之间切换。

3

我有两个窗体,subForm是由Form1中的buttonClick调用/创建的。目前我可以启动subForm,隐藏Form1,然后在subForm关闭时取消隐藏Form1。我希望能做到以下几点:

  1. 如果用户点击changeform按钮,请检查subForm是否处于活动但已隐藏状态
  2. 如果否,则启动subForm,否则隐藏Form1,取消隐藏subForm并将控制权传递给它
  3. 如果用户单击subForm的changeform按钮,则隐藏subForm,取消隐藏Form1,并将控制权传递给它
  4. 如果用户单击表单右上角的“X”,则关闭应用程序,无论哪个窗体处于活动状态。(现在,选择“X”会关闭subForm并打开/取消隐藏Form1。)

我可以找到解决部分要求的解决方案(也许全部,但我太菜了不知道)。重申我之前的问题,我目前拥有的代码是:

Form1

    private void countClick(object sender, EventArgs e)
    {
        this.Hide(); 
        subForm myNewForm = new subForm();
        myNewForm.ShowDialog();
        this.Show();
        countSelect.Checked = false;
    }

和子表单

    private void totalClick(object sender, EventArgs e)
    {
        this.Close();
    }

这个方法有效,但不够优雅。

@musefan 这就是我的原始问题,这些代码片段展示了答案。 - Peter Ladd
4个回答

2
我认为最好的方式是自己编写ApplicationContext。这样可以完全控制应用程序的生命周期,而无需将其绑定到特定的窗口。有关更多信息,请参见http://msdn.microsoft.com/en-us/library/ms157901.aspx
下面是一个例子:
static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MyApplicationContext());
    }
}

public class MyApplicationContext : ApplicationContext
{
    public MyApplicationContext()
    {
        ShowForm1();
    }

    public void ShowForm1()
    {
        if (_form2 != null)
            _form2.Hide();
        if (_form1 == null)
        {
            _form1 = new Form1(this);
            _form1.FormClosed += OnFormClosed;
        }
        _form1.Show();
        MainForm = _form1;
    }

    public void ShowForm2()
    {
        if (_form1 != null)
            _form1.Hide();
        if (_form2 == null)
        {
            _form2 = new Form2(this);
            _form2.FormClosed += OnFormClosed;
        }
        _form2.Show();
        MainForm = _form2;
    }

    private void OnFormClosed(object sender, FormClosedEventArgs e)
    {
        if (_form1 != null)
        {
            _form1.Dispose();
            _form1 = null;
        }
        if (_form2 != null)
        {
            _form2.Dispose();
            _form2 = null;
        }
        ExitThread();
    }

    private Form1 _form1;
    private Form2 _form2;
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    public Form1(MyApplicationContext context)
        : this()
    {
        _context = context;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (_context != null)
            _context.ShowForm2();
    }

    private readonly MyApplicationContext _context;
}

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    public Form2(MyApplicationContext context)
        : this()
    {
        _context = context;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (_context != null)
            _context.ShowForm1();
    }

    private readonly MyApplicationContext _context;
}

2

因此,我们将从子表单开始,创建一个新事件,用于在需要更改表单时通知父表单:

public event Action ChangeForm;

当子表单想要切换表单时,我们触发事件并隐藏子表单:

private void ChangeForm_Click(object sender, EventArgs e)
{
    Hide();
    if (ChangeForm != null)
        ChangeForm();
}

父表单需要将子表单实例化后作为一个实例字段:
私有 subForm child = new subForm();
并且它需要在其构造函数中初始化,同时添加处理程序到ChangeForm事件来显示父表单,并添加到关闭事件以关闭自身:
public Form1()
{
    InitializeComponent();

    child.ChangeForm += () => Show();
    child.FormClosed += (s, args) => Close();
}

然后,唯一剩下的就是父表单在想要更改表单时隐藏自身并显示子表单:

private void ChangeForm_Click(object sender, EventArgs e)
{
    Hide();
    child.Show();
}

谢谢您的快速回复。实际上,感谢所有回答的人。这是我采取的方法,一切都正常工作。再次感谢。 - Peter Ladd
1
form2.Closed += (s, args) => this.Close(); 请问这句话的作用是什么?(s,args) 是什么意思?Lambda 运算符 (=>) 的作用是什么? - Yash Saraiya
@YashSaraiya 似乎你已经知道这是一个lambda,所以你可以简单地搜索你想了解的任何信息。 - Servy
@Servy,我已经解决了lambda的问题,但(s, args)是什么意思?你能解释一下吗? - Yash Saraiya
@YashSaraiya 那些是lambda的参数。 - Servy
显示剩余2条评论

0
为什么不直接将它们设置为前景、最顶层等,然后再相反地设置回去呢?
——作为建议添加的评论

他并没有将父窗体的引用传递给子窗体,那你为什么要告诉他不要这样做呢? - Servy
this.MainFormRef_Field = MainFormRef;这是什么? - icbytes
那是其他用户的回答,不是原帖作者的。如果您想回应它,也许您应该在那个回答下留言。 - Servy

-1

subForm访问MainForm:

在您的subForm中创建一个构造函数和一个字段:

MainForm MainFormRef_Field;
subForm(MainForm MainFormRef)
{
    this.MainFormRef_Field = MainFormRef;
}

现在您可以使用此引用访问您的MainForm。像这样:

MainFormRef_Field.Show();
MainFormRef_Field.Hide(); //or how ever you want to handle it

MainForm访问subForm:

要处理您的subForm,请使用为其创建的对象。在这里:

subForm myNewForm = new subForm();

如果任何一个窗体关闭,则关闭整个应用程序:

为两个窗体设置Form_Closing事件:

private void MainForm_Closing(object sender, EventArgs e)
{
    Application.Exit();
}

private void subForm_Closing(object sender, EventArgs e)
{
    Application.Exit();
}

注意:

我不会为你的所有情况编写整个代码。设置变量,检查条件。如何编写代码完全取决于你。我已经为你提供了所需的所有主要要点的解决方案。


我没有做过这件事。不知道为什么它会出现在那里。 - Peter Ladd
我也不是原作者,但我在这里放了我的一部分答案(因为它更与你的答案相关,而不是与OP的问题相关):从子窗体访问父窗体是不好的风格和交叉引用。 更好的方法是将子窗体设置为弹出窗口并对对话框结果或类似内容做出反应。或者对父窗体上的其他事件做出反应。 但不要将父引用传递给子窗体。 - icbytes

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