2010-10-29 18 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