当出现验证错误时,防止丢失TextBox焦点的最佳方法是什么?

时间:2010-01-29 16:21:42

标签: wpf validation textbox wpf-controls focus

我和PreviewLostKeyboardFocus混淆了几乎让你到达那里。我已经看过使用LostFocus的几个实现,但这只会在失去焦点后强制重新关注TextBox并且您可以轻松地在屏幕上看到这种移动。基本上,我只是在WinForms中使用OnValidating寻找相同类型的行为。

3 个答案:

答案 0 :(得分:5)

在我看来,最好的方法通常是不要这样做。最好只禁用其他控件或阻止保存,直到值有效。

但如果你的设计确实需要这种能力,那么你应该做的就是:

  1. 在您的窗口级别截取Preview版本的键盘和鼠标事件,或者您希望阻止焦点更改的任何范围(例如,可能不是您的菜单栏)。

  2. 当在文本框中检测到Tab KeyDown或Return KeyDown时,或者当文本框中具有焦点时检测到MouseDown时,请在绑定表达式上调用UpdateSource(),如果验证有failed set Handled = true以防止进一步处理KeyDown或MouseDown事件。

  3. 同时继续处理PreviewLostKeyboardFocus以捕捉不是来自键盘或鼠标或您的其他代码无法识别的任何焦点更改原因。

答案 1 :(得分:2)

添加到Ray的答案:

UpdateSource的调用如下:

BindingExpression be = userTextbox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();

另外,您也可以将文本框绑定设置为:

UpdateSourceTrigger = "PropertyChanged";

后者将导致连续检查,而前者将在需要时进行检查(性能)。

答案 2 :(得分:1)

如果你试图将一个元素集中在它自己的LostFocus处理程序中,你将面临一个StackOverflowException,我不确定根本原因(我怀疑焦点类型反弹)但是有一个简单的解决方法:发送它。

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
    var element = (sender as TextBox);
    if (!theTextBoxWasValidated())
    {
        // doing this would cause a StackOverflowException
        // element.Focus();
        var restoreFocus = (System.Threading.ThreadStart)delegate { element.Focus(); };
        Dispatcher.BeginInvoke(restoreFocus);
    }
}

通过Dispatcher.BeginInvoke,您确保恢复焦点不会妨碍正在进行的焦点丢失(并避免您面临的令人讨厌的异常)