winforms 如何在更改窗体后重新打开窗体以不丢失输入数据

h22fl7wq  于 2022-11-17  发布在  其他
关注(0)|答案(2)|浏览(189)

我有多个表单,但现在只有2个。一个主表单加载到应用午餐上,另一个在用户从侧菜单中选择它时出现。问题是,如果用户再次点击菜单,它会创建一个新表单,而不是保持原来的表单。如果他们改变表单,会发生一些事情。
下面是处理Click事件的当前代码。

private Form activeForm = null;

private void openChildForm(Form childForm)
{
        if (activeForm != null)
        {
            activeForm.Close();
        }                

        activeForm = childForm;
        childForm.TopLevel = false;
        childForm.FormBorderStyle = FormBorderStyle.None;
        childForm.Dock = DockStyle.Fill;

        this.panelChildForm.Controls.Add(childForm);
        this.panelChildForm.Tag = childForm;

        childForm.BringToFront();
        childForm.Show();
}

private void btnFalderon_Terminal_Click(object sender, EventArgs e)
{
    openChildForm(new FalderonTerminal());
}

那么,我需要对代码做什么修改,才能理解和检查表单是否已经打开并显示相同的表单,这样我就不会在表单上遗漏信息。就像在这个例子中,在“FalderonTerminal”表单上进行串行连接。
UPDATE:所以我对条件做了一些修改,它会查看表单是否已经打开。但是它似乎总是创建一个新表单,而不是使用旧表单:/

private void btnFalderon_Terminal_Click(object sender, EventArgs e)
    {
        if (Application.OpenForms.OfType<FalderonTerminal>().Any())
        {
            Application.OpenForms.OfType<FalderonTerminal>().First().BringToFront();
            System.Diagnostics.Debug.WriteLine("Old Falderon Terminal");
        }
        else
        {
            System.Diagnostics.Debug.WriteLine("New Falderon Terminal");
            openChildForm(new FalderonTerminal());
        }
        
    }
2admgd59

2admgd591#

如果表单不是null也不是IsDisposed,你应该可以只显示它。这个代码的问题是关闭它会导致它被释放。在这种情况下,(IsDispose || Disposing)new创建一个新的副本(childForm = new ChildForm()),它将以一个干净的表单重新开始。

7nbnzgx9

7nbnzgx92#

您应该了解modal dialog box and a modeless dialog boxmodal dialog box and a modeless dialog box之间的差异。对话框的类型会影响您在主窗体中使用它的方式。

模态对话框

模式对话框在操作员可以使用主窗体之前关闭。只要显示模式对话框,就不会调用主窗体的用户输入事件。
这个的使用结构与下面的类似。主窗体中的一个 * 文件保存为 * 模式对话框的示例:

public void OnMenuFileSaveAs_Clicked(object sender, ...)
{
    this.FileSaveAs();
}

和文件另存为:

public void FileSaveAs()
{
    using (SaveFileDialog dialog = new SaveFileDialog())
    {
        // if needed set some properties of SaveFileDialog
        dialog.Title = "File Save As";
        dialog.InitialDirectory = ...
        dialog.AddExtension = ...

        // Show the dialog and wait until the operator is finished
        DialogResult dlgResult = dialog.ShowDialog(this);

        switch (dlgResult)
        {
        case DialogResult.Ok:
             // operator selected a file name
             string fileName = dialog.FileName;
             this.SaveFileAs(fileName);
             break;

        case DialogResult.Cancel:
             // operator cancelled file save as
             this.CancelSaveFileAs();
             break;

        // etc.
        }
    }
}

“模式”对话框仅在使用此方法时存在。只要模式对话框未关闭,就无法访问主窗体。

无模式对话框

您想要显示非胁迫回应对话方块。当此对话方块显示时,操作员仍然可以行程主表单。这表示您必须在非胁迫回应对话方块关闭之前,从主表单中的事件行程常式传回。因此,您应该记住非胁迫回应对话方块。
当非胁迫回应对话方块未关闭时,应该停用所有可以再次开启非胁迫回应对话方块的功能。
一个很好的方法是禁用(灰显)可以打开此对话框的按钮和菜单项。第二个方法是保持控件启用,并在单击控件(按钮/菜单项)时将焦点放在非模态对话框上。

private MyModelessDialog ModelessDialog {get; set} = null;

private bool IsModelessDialogShown => this.ModelessDialog != null;

public void OnMenuShowModelessClicked(object sender, ...)
{
    // only open the modeless dialog box if not shown yet
    if (!this.IsModelessDialogShown)
    {
        // if desired, make sure that the menu item is disabled
        this.DisableMenuItemShowModeless();

        this.ShowModelessDialogBox();
    }
    else
    {
        // either do nothing, or decide to give the focus to the modeless dialog box
        this.SetFocusOnModelessDialogBox();
    }
}

private void DisableMenuItemShowModeless()
{
    this.menuItemShowModeless.Enabled = false;
    // is there also a button? Disable this as well
}

private void EnableMenuItemShowModeless()
{
    this.menuItemShowModeless.Enabled = true;
    // is there also a button? Enable this as well
}

您可以使用control.Focus()将焦点给予非胁迫回应对话方块上。如何正确地完成这项工作不在本问题的范围内。

private void ShowModelessDialogBox()
{
    // Create a new modeless dialog box object, and set some properties
    this.ModelessDialogBox = new MyModelessDialogBox()
    {
        ...
    }

    // make sure I get called when the modeless dialog box closes
    this.ModelessDialogBox.Closed += this.ModelessDialogBox_Closed;

    // Show the modeless dialog box as a modeless dialog box:
    this.ModelessDialogBox.Show(this);
}

此时将显示无模式对话框。操作员既可以处理无模式对话框,也可以处理主窗体。菜单项被禁用,因此操作员无法单击它。如果选择不禁用它,则单击它时不会显示新的模式对话框。模型对话框将获得焦点。
当对话框关闭时,主窗体将收到通知:

private void ModelessDialogBox_Closed(object sender, EventArgs e)
{
    if (Object.ReferenceEquals(sender, this.ModelessDialogBox)
    {
        this.ModelessDialogBox_Closed();
    }
}

private void ModelessDialogBox_Closed()
{
    // if needed read and process properties of the modeless DialogBox
    this.ProcessModelessDialogBoxResults(this.ModelessDialogBox);

    this.ModelessDialogBox -= ModelessDialogBox_Closed;
    this.ModelessDialogBox.Dispose();
    this.ModelessDialogBox = null;

    this.EnableMenuItemShowModelesss();
}

因为我停用了显示新非胁迫回应对话方块的功能表项目,所以只会显示一个方块。如果您选择不停用功能表项目,则按一下它会将焦点设定在非胁迫回应对话方块上。
最后一点:你有没有注意到我用了很多小程序而不是用几个程序来完成所有的事情。2这为你的程序做好了修改的准备,例如,如果你决定添加一个按钮而不是仅仅一个菜单项。3或者,如果你需要禁用几个菜单项。4或者,如果你决定在将来的版本中不再禁用菜单项。5小程序也使重用和单元测试更容易。
请注意,如果您在非胁迫回应对话方块仍在显示时关闭主视窗,则非胁迫回应对话方块也会关闭,因为它的父代已关闭。除了操作员没有机会对非胁迫回应对话方块的结果做出React之外,其他一切都行程得很好。如果您不想这样,请订阅主表单的IsClosing事件,并核取IsModelessDialogBoxShown。如果是这样,请决定要做什麽:取消关闭?警告操作员对话框已打开?

相关问题