2010-12-16 36 views
6

我有一個WinForm應用程序,在窗體上有幾個輸入控件。在驗證事件處理程序(ValidatingValidated)中,我需要根據驗證的值確定下一個要激活的控件。如何在.NET中進行驗證後將焦點設置爲控件

Validating事件的微軟的文檔,它指出:

注意

不要試圖從輸入,的GotFocus,離開,引發LostFocus,確認內設置焦點,或驗證的事件處理程序。否則可能導致您的應用程序或操作系統停止響應。有關詳細信息,請參閱「鍵盤輸入參考」一節中的WM_KILLFOCUS主題以及MSDN庫中「關於消息和消息隊列」主題的「消息死鎖」一節,主題爲http:// msdn.microsoft.com/library 。

對於Form類,有一個ActiveControl屬性,它允許設置要變爲活動的控件,並且不提及任何限制。經過幾個小時的網絡搜索後,我還沒有找到任何其他解決方案。

是從我的驗證事件處理程序設置ActiveControl屬性(而不是Focus)一個安全的方式來積極激活我想要的控件?如果沒有,有沒有解決辦法?

由於.NET Compact Framework沒有ActiveControl屬性,任何人都可以提出解決方案嗎?

回答

9

是的,驗證事件中改變焦點是相當麻煩的。焦點發生變化時,事件將會發生。就Windows而言,下一個控件已經獲得了重點,但邏輯形式狀態仍然關注於正在驗證的控件。當您將e.Cancel設置爲true時,Winforms必須撤消Windows焦點狀態。如果不這樣做,它必須在事件發生後更新邏輯狀態。當你改變自己的注意力時,會出現各種各樣的錯誤。

重要的是你要等到焦點被整理出來。最好的辦法是延遲你的代碼,直到一切完成並且表單再次空閒。你可以通過使用Control.BeginInvoke()方法乾淨地這樣做。事情是這樣的:

private delegate void ChangeFocusDelegate(Control ctl); 

    private void textBox1_Validating(object sender, CancelEventArgs e) { 
     int value; 
     if (!int.TryParse(textBox1.Text, out value)) e.Cancel = true; 
     else { 
      if (value == 1) this.BeginInvoke(new ChangeFocusDelegate(changeFocus), textBox2); 
      else this.BeginInvoke(new ChangeFocusDelegate(changeFocus), textBox3); 
     } 
    } 
    private void changeFocus(Control ctl) { 
     ctl.Focus(); 
    } 
+0

哇,聰明的答案!我認爲委託方法必須調用EndInvoke(),但是在我知道Delegate.BeginInvoke()和Control.BeginInvoke()之間的區別之前。請參閱\t [.net - Invoke()和BeginInvoke之間的區別是什麼] [1] [1] http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke – Suncat2000 2011-02-11 19:13:49

1

您是否曾嘗試將傳遞到Validating事件處理函數的CancelEventArgsCancel property設置爲False?

這是一種專注於當前控制並防止下一次控制在驗證失敗時獲得焦點的預期方式。例如:

private void TextBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e) 
{ 
    //Make sure that the textbox is not left blank 
    if (string.IsNullOrEmpty(TextBox1.Text)) 
    { 
     e.Cancel = true; 
    } 
} 
+0

謝謝。我知道這一點,但它只保持焦點不變。它不允許將焦點設置爲特定的控件。 – Suncat2000 2011-02-11 14:37:52

+0

@Suncat:是的,我不知道你想把焦點設置爲*不同的控件。漢斯已經給了你如何做到這一點的好回答。 – 2011-02-12 04:09:11

0

這個線程是老了,但我有一對夫婦的想法:

  1. 每個控件具有Tag屬性。關於給予你想要的控件,關注一個獨特的Tag值,然後創建一個方法來遍歷控件以找到該控件?然後你可以設置焦點。

  2. 而不是使用Validating事件,爲什麼不使用Leaving來代替?似乎沒有相同的怪癖。

相關問題