2010-10-29 15 views
1

我正在写一个Windows应用程序,基本上在后台运行与通知图标与它进行交互。通知图标可以执行基本的操作,例如退出应用程序或显示有关它的信息。它也可以启动一个模态配置对话框。表单打开为模式对话框关闭按钮时,即使虽然关闭()不叫

创建对话的代码是非常简单的:

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

    frmSettings.ShowDialog(); 
} 

SettingsForm类基本上有三个GroupBox控制,在每一个LabelTextBox控制,并在底部4个Button控制:"Advanced...""Restore Defaults""Cancel""Apply"。每个TextBox都有一个Validating事件处理程序通过设计器连接起来。每个按钮都有一个Click处理器通过设计器连接起来。他们每个人都会做很明显的事情:打开另一个具有更高级设置的模式对话框,将文本框恢复为默认值,关闭对话框或保存更改,触发ConfigurationChanged事件,然后然后关闭对话框所有的字段都是有效的!)。

当出现表单输入错误时,我通过设置((CancelEventArgs)e).Cancel = true来取消相应的Validating事件。但是,这两种形式的默认行为是为了防止用户在验证失败时改变焦点。我发现这非常讨厌,最终发现在设计选项,当用户离开现场还自动验证,而是让他们离开,即使验证失败:AutoValidate = EnableAllowFocusChange [1]

"Apply"按钮Click处理器看起来基本上是这样的:

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

我正在打破第一线并通过线法线步进测试出的代码。实质上,ValidateChildren正如预期的那样返回错误,并且整个if块,包括this.Close()都被跳过。然而,如果我一直走到方法的底部,然后走出去,我最终回到frmSettingsForm.ShowDialog()行,并且表单神奇地关闭。

"Apply"按钮被设置为表格的AcceptButton。我不知道它是否隐式地将一个处理程序附加到按钮的事件,以便在按下按钮时自动关闭窗体。这听起来不像是逻辑上应该假设的,特别是考虑到似乎没有办法取消事件,但这是我能想出的唯一解释。为了验证这一理论,我试图在设计器中取消设置AcceptButton,但是当数据无效时,我的表单仍然关闭。

什么是关闭我的表单,我该如何阻止它?

[1]:如果其他人无法找到它,它是一个表单属性,而不是每个单独控件的属性(正如我预期的那样)。

+0

重写'OnClosing'并告诉我们'CloseReason'是什么。在那里设置一个断点,并检查你的字段的状态,看看是否有任何线索。 – 2010-10-29 16:29:15

+0

关闭的原因是'没有'。 : - /我的领域的状态是预期的(其中两个文本框是空的,但它们都是必需的)。 – bambams 2010-10-29 16:43:53

回答

9

您是否拥有ButtonDialogResult集?如果是这样,当您单击Button时,FormDialogResult将设置为该值,并且模型Form将关闭。为了防止这种情况发生,当处理器中的验证失败时,将FormDialogResult设置为DialogResult.None

+0

谢谢,这似乎解决了问题!我没有明确地将'DialogResult'设置为之前的任何内容,所以它必须被隐式设置(或默认为“None”以外的内容)。似乎有点狡猾,但我想它必须适用于大多数形式。无论如何,我只是添加了一个else块,并按照你的建议(和'catch'块)将它设置为'None',并且它似乎是固定的! – bambams 2010-10-29 16:38:32

+0

当你将'Button'设置为'Form.AcceptButton'时,它可能会自动设置。我在VS2008中试过了,它并没有这样做,但也许你正在使用不同的版本,或者你有一些补充,这是为你做的。 – 2010-10-29 16:41:09

+0

我正在使用VS2010和.NET 4.自VS2008/3.5以来,事情可能已经发生了变化? – bambams 2010-10-29 16:45:56

0

我不知道为什么发生这种情况,但是你可以重写事件OnFormClosing,并根据您的逻辑检查的的DialogResult值。

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