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

WPF Prism:调用Keyboard.ClearFocus()时TextBox的LostFocus命令未触发求解

问题

在WPF Prism项目中,TextBox获取或失去焦点时,ViewModel中的MyMethod方法可正常调用,但通过Keyboard.ClearFocus()清除焦点时,该方法不会触发。求更优解决方案或指出操作中的错误。

视图(View)

<TextBox x:Name="MyTextBox" HorizontalAlignment="Left" Margin="35,237,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding MyTextBoxText}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="LostFocus">
            <prism:InvokeCommandAction Command="{Binding MyCommand}">
                <prism:InvokeCommandAction.CommandParameter>
                    <MultiBinding Converter="{StaticResource multiParameterConverter}">
                        <Binding Path="Name" ElementName="MyTextBox"/>
                        <Binding Path="IsFocused" ElementName="MyTextBox"/>
                    </MultiBinding>
                </prism:InvokeCommandAction.CommandParameter>
            </prism:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>

视图模型(ViewModel)

public DelegateCommand<object> MyCommand=>
      _myCommand ??= new DelegateCommand<object>(MyMethod);  

private void MyMethod(object myObject)
{
  //Do something
}

代码后置(Code Behind)

private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
   Keyboard.ClearFocus();
}

解决方案

问题原因

Keyboard.ClearFocus()会将焦点设置到WPF内部的UnfocusedElement,这个过程不会触发TextBox的LostFocus事件——该事件仅在焦点转移到另一个可聚焦的UI元素时才会触发,而非完全清除焦点的场景。

方案1:手动触发LostFocus事件

在执行Keyboard.ClearFocus()前,主动触发TextBox的LostFocus事件,确保命令被执行:

private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    MyTextBox.RaiseEvent(new RoutedEventArgs(UIElement.LostFocusEvent));
    Keyboard.ClearFocus();
}

方案2:绑定IsFocused属性到ViewModel(更符合MVVM)

放弃事件触发的方式,直接将TextBox的IsFocused属性双向绑定到ViewModel的属性,在属性变更时执行MyMethod:

  • 视图修改:
<TextBox x:Name="MyTextBox" 
         HorizontalAlignment="Left" 
         Margin="35,237,0,0" 
         TextWrapping="Wrap" 
         VerticalAlignment="Top" 
         Text="{Binding MyTextBoxText}"
         IsFocused="{Binding IsTextBoxFocused, Mode=TwoWay}"/>
  • 视图模型补充代码:
private bool _isTextBoxFocused;
public bool IsTextBoxFocused
{
    get => _isTextBoxFocused;
    set
    {
        if (SetProperty(ref _isTextBoxFocused, value) && !value)
        {
            // 当焦点从TextBox移除时执行方法,可根据原多绑定逻辑构造参数
            var parameters = new object[] { MyTextBox.Name, false };
            MyMethod(yourMultiConverter.Convert(parameters, typeof(object), null, CultureInfo.CurrentCulture));
        }
    }
}

这种方式无需依赖事件,只要IsFocused变为false,无论焦点是正常转移还是被清除,都会执行目标方法,更贴合MVVM设计思想。

方案3:将焦点转移到父容器

替代Keyboard.ClearFocus(),把焦点设置到可聚焦的父容器(如Grid),这样TextBox会正常触发LostFocus事件:

  • 父容器需设置Focusable="True":
<Grid Focusable="True" MouseLeftButtonDown="Grid_MouseLeftButtonDown">
    <!-- 包含TextBox等元素 -->
</Grid>
  • 代码后置修改:
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (sender is Grid parentGrid)
    {
        FocusManager.SetFocusedElement(parentGrid, parentGrid);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 04:14:56