WPF學習拾遺(三)TextBox焦點問題


這是項目里的一個問題點,組里的同學在設置Focus事件時候,遇到了死鎖,最后StackOverFlow。

寫一個小例子

一個Textbox控件輸入值,一個TextBlock顯示結果,一個檢索Button

TextBox框里輸入一個ID,去系統里檢索一個值,把結果顯示在TextBlock里。

當查詢不到結果時候把焦點停留在TextBox里,當然觸發的條件有TextBox失去焦點時

和按檢索Button時。對於測試焦點的小例子,我們當然不用去連數據庫,寫個簡單的方法

如果輸入的值為【123】時候返回結果AAA,輸入其他以外的結果表示不存在,把焦點停留在

Textbox里

很多沒有同學開始寫的時候都會Button_Click方法和Textbox_LostFocus方法去實現自己

的代碼,Button_Click事件一點問題也沒有,但是LostFocus時候卻反生了異常終了,百思不得其解。

今天我們就來解決2個問題,為什么會不行?該怎么解決?

【原因】

請看一段

    Private Shared Sub IsFocused_Changed(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim source As UIElement = DirectCast(d, UIElement)
        If CBool(e.NewValue) Then
            source.OnGotFocus(New RoutedEventArgs(UIElement.GotFocusEvent, source))
        Else
            source.OnLostFocus(New RoutedEventArgs(UIElement.LostFocusEvent, source))
        End If
    End Sub

    Public ReadOnly Property IsFocused As Boolean
        Get
            Return CBool(MyBase.GetValue(UIElement.IsFocusedProperty))
        End Get
    End Property

   Friend Shared ReadOnly IsFocusedPropertyKey As DependencyPropertyKey = DependencyProperty.RegisterReadOnly("IsFocused", GetType(Boolean), GetType(UIElement), New PropertyMetadata(BooleanBoxes.FalseBox, New PropertyChangedCallback(AddressOf UIElement.IsFocused_Changed)))

   Public Custom Event LostFocus As RoutedEventHandler
        AddHandler(ByVal value As RoutedEventHandler)
            Me.AddHandler(UIElement.LostFocusEvent, value)
        End AddHandler
        RemoveHandler(ByVal value As RoutedEventHandler)
            Me.RemoveHandler(UIElement.LostFocusEvent, value)
        End RemoveHandler
    End Event


LostFocus事件沒有前置事件,所以不能e.Handled=True去控制,所以他被設置成一個只能執行的方法,擁有一個IsFocused的依賴屬性,當我們在寫代碼時候

前置寫方法Textbox1.Focus()時候,就造成LostFoucs事件沒有結束,還不能結束,進程互相等待,最后StackOverFLow

【解決方法】

1.替換事件

改用LostKeyBoardFocus事件。這個是在System.Windows.Input中完全是對於鍵盤事件的方法。當焦點完全離開對象時候,該事件才被觸發

所以把LostFocus的處理寫在LostKeyBoardFocus里就能解決上述問題

    [SecurityCritical]
    private static void OnLostKeyboardFocusThunk(object sender, KeyboardFocusChangedEventArgs e)
    {
      Invariant.Assert(!e.Handled, "Unexpected: Event has already been handled.");
      UIElement uiElement = sender as UIElement;
      if (uiElement != null)
      {
        uiElement.OnLostKeyboardFocus(e);
      }
      else
      {
        ContentElement contentElement = sender as ContentElement;
        if (contentElement != null)
          contentElement.OnLostKeyboardFocus(e);
        else
          ((UIElement3D) sender).OnLostKeyboardFocus(e);
      }
    }

 

2.使用Dispatcher.BeginInvoke用異步的方法來更新

把更新Focus這件事放入UI進程的隊列中,等待前一處理結束后,進行設置

    Private Sub TextBox1_LostFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles TextBox1.LostFocus
        If Trim(TextBox1.Text).Equals("123") Then
            TextBlock2.Text = "AAA"
        Else
            TextBlock2.Text = String.Empty
            Me.Dispatcher.BeginInvoke(DispatcherPriority.Render, New Action(Sub() TextBox1.Focus()))
        End If
    End Sub

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM