You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF C# 鼠标左键按下触发焦点丢失时获取源控件并重聚焦问题

WPF TextBox 失焦校验拦截焦点解决方案

核心问题原因

你在LostFocus事件中设置焦点不生效,是因为LostFocus是冒泡事件,触发时新控件的焦点获取逻辑已经进入事件队列,你直接调用Focus()的操作会被后续的焦点转移逻辑覆盖,自然也无法阻止焦点跳转。

最优解决方案:使用PreviewLostKeyboardFocus隧道事件

这个事件在焦点真正完成转移前触发,你可以直接中断焦点路由,完全避免焦点跳走的问题,同时事件的sender参数就是你需要的失焦源控件,无需额外捕获。

单控件绑定示例

XAML代码:

<TextBox x:Name="InputTextBox" PreviewLostKeyboardFocus="InputTextBox_PreviewLostKeyboardFocus" />

后台事件代码:

private void InputTextBox_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    var sourceTextBox = sender as TextBox;
    if (sourceTextBox == null) return;

    // 替换为你的自定义校验逻辑
    bool isInputValid = !string.IsNullOrWhiteSpace(sourceTextBox.Text) && int.TryParse(sourceTextBox.Text, out _);
    if (!isInputValid)
    {
        // 中断事件路由,阻止焦点转移
        e.Handled = true;
        // 可选配置:标红控件、全选文本方便用户直接修改
        sourceTextBox.BorderBrush = Brushes.Red;
        sourceTextBox.SelectAll();
    }
    else
    {
        sourceTextBox.ClearValue(TextBox.BorderBrushProperty);
    }
}

全局拦截所有TextBox失焦操作

如果需要对窗口内所有TextBox统一做校验拦截,无需逐个绑定事件,在窗口构造函数中添加全局事件注册即可:

public MainWindow()
{
    InitializeComponent();
    // 注册全局TextBox失焦前事件处理
    EventManager.RegisterClassHandler(typeof(TextBox), TextBox.PreviewLostKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(GlobalTextBoxPreviewLostFocus), true);
}

private void GlobalTextBoxPreviewLostFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    // 同上写入校验逻辑即可,sender为当前失焦的TextBox控件
}

兼容方案:LostFocus事件异步设置焦点

如果你必须沿用LostFocus事件的现有逻辑,可以通过Dispatcher把焦点设置操作排到当前焦点处理逻辑之后执行,也能实现焦点回切,缺点是会有轻微的焦点闪烁:

private void InputTextBox_LostFocus(object sender, RoutedEventArgs e)
{
    var sourceTextBox = sender as TextBox;
    if (sourceTextBox == null) return;

    bool isInputValid = !string.IsNullOrWhiteSpace(sourceTextBox.Text) && int.TryParse(sourceTextBox.Text, out _);
    if (!isInputValid)
    {
        // 异步设置焦点,优先级设为Input确保在当前焦点转移完成后执行
        Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input, new Action(() =>
        {
            sourceTextBox.Focus();
            sourceTextBox.SelectAll();
        }));
    }
}

内容的提问来源于stack exchange,提问作者Perini Luca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 13:18:02