Home > database >  Keep dialog form from unloading when closed
Keep dialog form from unloading when closed

Time:12-07

I have a dialog window with a listbox containing >3000 items that takes a long time to initially load. To load this dialog, I created an instance var dlg = new frmDlg(); and then when I need this dialog, I open it with dlg.ShowDialog(this); Although this reduced the number of time the listbox needs to be initialized, it still takes a long time to show the form as the dialog is unloaded from memory after the dialog closes, requiring the visual elements to be reloaded. Is there any way to keep this from happening? With a normal form, I would just hide the window instead of closing it, but this does not seem to work for dialog windows.

CodePudding user response:

Add the following members to the frmDlg:

private bool keepHandle;

protected override void OnFormClosing(FormClosingEventArgs e)
{
    keepHandle = e.CloseReason == CloseReason.UserClosing;
    base.OnFormClosing(e);
}

protected override void DestroyHandle()
{
    if (!keepHandle)
        base.DestroyHandle();
}

This should prevent the dialog's handle from being destroyed when the dialog closed by the user.

CodePudding user response:

Form1:

public partial class Form1 : Form
{
    private Form2 reusable = null;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (reusable == null) reusable = new Form2();

        reusable.ShowDialog(this);
        switch (reusable.DialogResult)
        {
            case DialogResult.OK: MessageBox.Show("Ok clicked."); break;
            case DialogResult.Cancel: MessageBox.Show("Cancel clicked."); break;
            case DialogResult.None: MessageBox.Show("Form Closed."); break;
        }
    }
}

Form2:

public partial class Form2 : Form
{
    private DialogResult dialogResult = DialogResult.None;
    public new DialogResult DialogResult
    {
        get => this.dialogResult;
        set => this.dialogResult = value;
    }

    public Form2()
    {
        InitializeComponent();
    }

    private void Form2_Shown(object sender, EventArgs e)
    {
        this.dialogResult = DialogResult.None;
    }

    private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        e.Cancel = true;
        this.Hide();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        this.dialogResult = DialogResult.OK;
        this.Close();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        this.dialogResult = DialogResult.Cancel;
        this.Close();
    }
}

^ Several caveats: you can no longer use the result from ShowDialog result, and you need to create your own DialogResult property, or just use a completely different / new property to represent how your dialog was hidden.

You also can't use the Button.DialogResult property anymore on any buttons, and you need to implement your own button click events to handle setting the dialog result.

This is all because of stuff that happens under the hood in the .net framework when you call ShowDialog result.

Also, Dmitry's example on using the e.CloseReason is valid too - you might want to allow closing for stuff like the application closing. That way you can also handle the FormClosed event and do any rapid cleanup you need to do before the application closes.

  • Related