简体   繁体   中英

Form Opened As Modal Dialog Closes When Button Is Pressed, Even Though Close() is not called

I'm writing a Windows application that basically runs in the background with a notification icon to interact with it. The notification icon can do basic things like exit the application or show information about it. It can also launch a modal configuration dialog.

The code that creates the dialog is pretty straightforward:

using(var frmSettings = new SettingsForm(configuration))
{
    frmSettings.ConfigurationChanged += ConfigurationChangedHandler;
    frmSettings.UnhandledException += UnhandledExceptionHandler;

    frmSettings.ShowDialog();
}

The SettingsForm class basically has three GroupBox controls, with a Label and TextBox control in each, and 4 Button controls at the bottom: "Advanced..." , "Restore Defaults" , "Cancel" , and "Apply" . Each TextBox has a Validating event handler wired up through the designer. Each button has a Click handler wired up through the designer. Each of them does pretty obvious things: opens another modal dialog with more advanced settings, restores the textboxes to their default values, closes the dialog, or saves the changes, fires the ConfigurationChanged event, and then closes the dialog (but only if all fields are valid!).

When there is a form entry error I cancel the corresponding Validating event by setting ((CancelEventArgs)e).Cancel = true . However, the default behavior of both forms was to prevent the user from changing focus when validation failed. I found this pretty annoying and eventually found the option in the designer to still automatically validate when the user leaves the field, but to allow them to leave even if validation fails: AutoValidate = EnableAllowFocusChange .[1]

My "Apply" button Click handler looks basically like this:

private void btnApply_Click(object sender, EventArgs e)
{
    try
    {
        if(this.ValidateChildren())
        {
            this.Configuration.Field1 = this.txtField1.Text;
            this.Configuration.Field2 = this.txtField2.Text;
            this.Configuration.Field3 = this.txtField3.Text;

            if(this.Configuration.Changed)
            {
                this.Configuration.Save();

                this.OnConfigurationChanged(new ConfigurationChangedEventArgs(
                        this.Configuration));
            }

            this.Close();
        }
    }
    catch(Exception ex)
    {
        this.OnUnhandledException(new UnhandledExceptionEventArgs(
                "Failed To Apply Configuration Settings",
                ex));
    }
}

I'm currently testing out the code by breaking on the first line and stepping through the method line by line. Essentially, ValidateChildren is returning false as expected and the entire if block, including the this.Close() are skipped. Yet, if I step all the way to the bottom of the method and then step out of it I end up back on the frmSettingsForm.ShowDialog() line and the form is magically closed.

The "Apply" button is set as the form's AcceptButton . I wonder if it's implicitly attached a handler to the button's Click event to automatically close the form when the button is pressed. That doesn't sound like it logically should be assumed, especially considering there doesn't seem to be a way to cancel the Click event, but it's the only explanation that I can come up with. To test that theory, I have tried unsetting the AcceptButton in the designer, but my form still closes when the data is invalid.

What is closing my form and how do I stop it?

[1]: If anybody else has trouble finding it, it's a form property, not a property of each individual control (as I expected it would be).

Do you have the DialogResult of the Button set? If so, when you click the Button , the DialogResult of the Form will be set to that value and the modal Form will close. To prevent this, when validation fails in your Click handler, set the Form 's DialogResult to DialogResult.None .

I don't know why that happens, but you could override the event OnFormClosing and check for the value of DialogResult according to your logic.

  If (DialogResult != Windows.Forms.DialogResult.Cancel )
            e.Cancel = True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM