【问题标题】:hide main form, start new form, switch between the two without closing second form隐藏主窗体,启动新窗体,在两者之间切换而不关闭第二个窗体
【发布时间】:2013-07-02 15:20:33
【问题描述】:

我有两个表单,其中 subForm 由 Form1 中的 buttonClick 调用/创建。现在我可以启动 subForm,隐藏 Form1,然后在 subForm 关闭时取消隐藏 Form1。我想做的是:

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

我可以找到满足部分要求的解决方案(也许是全部,我只是太菜鸟不知道)。在这里重复我之前的问题,我到目前为止的代码是:

表格1

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

这可行,但不是很优雅。

【问题讨论】:

标签: c# winforms visual-studio-2012


【解决方案1】:

我认为最好的方法是推出自己的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();
    }
    

    父表单需要一个子表单的实例作为实例字段:

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

    【讨论】:

    • 感谢您的快速回复。其实,感谢所有回答的人。这是我采取的路线,一切正常。再次感谢。
    • form2.Closed += (s, args) => this.Close(); 我可以知道这个语句是如何工作的吗? (s,args) 到底是什么? lambda 运算符 (=>) 有什么用?
    • @YashSaraiya 听起来您已经知道它是一个 lambda,因此您可以简单地搜索您想了解的任何内容。
    • @Servy 我得到了 lambda 的排序,但是 (s, args) 呢?你能解释一下吗?
    • @YashSaraiya 这些是 lambda 的参数。
    【解决方案3】:

    为什么不简单地将它们设置为前景、顶部等等? 反之亦然?

    ---按照建议添加为评论

    【讨论】:

    • 没有将父表单的引用传递给子表单,那么你为什么告诉他不要这样做呢?
    • this.MainFormRef_Field = MainFormRef;这是什么?
    • 这是其他用户的回答,而不是 OP。如果您想回复它,也许您应该评论该答案。
    【解决方案4】:

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

    注意:

    我不会为您的所有案例编写完整的代码。设置变量,检查条件。这完全取决于您如何编码。您需要的所有要点我都为您提供了解决方案。

    【讨论】:

    • 我没有这样做。不知道为什么会在那里。
    • 也不是我,但我将部分答案放在这里(因为它更多地指的是你的答案而不是 OP 的问题:Accessing parent-form from child form is bad style and cross reference . 更好的方法是使子窗体作为弹出窗口并对对话框结果或类似的结果做出反应。或者对父窗体上的其他事件作出反应。但不将父引用传递给子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2018-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多