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
相关产品推荐
相关产品推荐

