这是项目里的一个问题点,组里的同学在设置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

 

 

 

posted on 2013-01-14 13:22  A神降临  阅读(5883)  评论(0编辑  收藏  举报