AutoSuggestBox在LosingFocus与LostFocus事件间丢失输入值的问题求助
AutoSuggestBox在LosingFocus与LostFocus事件间丢失输入值的问题求助
我遇到了一个十分棘手的问题:当从某个特定的AutoSuggestBox中按Tab键切换焦点时,它的输入值会在LosingFocus和LostFocus事件之间被莫名清空。
更奇怪的是,这个问题只出现在我应用里的这一个AutoSuggestBox实例上,其他功能类似甚至配置完全相同的AutoSuggestBox都能正常工作,完全没这个问题。
最小可复现示例
XAML代码
<AutoSuggestBox Text="{x:Bind ViewModel.Value, Mode=TwoWay}" ItemsSource="{x:Bind ViewModel.VisibleValues, Mode=OneWay}" TextMemberPath="TextMember" DisplayMemberPath="TextMember" LosingFocus="TestLosingFocus" LostFocus="TestLostFocus" />
C#事件处理代码
// ... private void TestLosingFocus(UIElement sender, LosingFocusEventArgs args) { string senderText = (sender as AutoSuggestBox).Text; // 此时值为输入的"abc" string vmText = ViewModel.Value; // 此时ViewModel的值也是"abc" } private void TestLostFocus(object sender, RoutedEventArgs e) { string senderText = (sender as AutoSuggestBox).Text; // 此时值为空字符串"" string vmText = ViewModel.Value; // ViewModel的值也变成了"" } // ...
复现步骤:在AutoSuggestBox中输入任意内容,然后按Tab键切换到Tab顺序中的下一个控件。值得注意的是,如果用鼠标点击其他控件移除焦点,就不会触发这个bug。
问题发生的详细过程
- LosingFocus事件阶段:按下Tab键切换焦点时,AutoSuggestBox先触发
LosingFocus事件,此时控件的Text属性和ViewModel的Value值都和输入内容完全一致,一切正常。 - 生成代码执行阶段:单步调试跳出
TestLosingFocus方法后,会执行一段WinRT生成代码中的函数(不会进入catch块),而且调试器无法单步进入try块内的语句,只能直接跳过。这段代码如下:
namespace WinRT.GenericTypeInstantiations; // ... internal static class Windows_Foundation_TypedEventHandler_2_Microsoft_UI_Xaml_UIElement__Microsoft_UI_Xaml_Input_LosingFocusEventArgs { // ... [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvStdcall) })] private static unsafe int Do_Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr args) { try { global::ABI.Windows.Foundation.TypedEventHandlerMethods<global::Microsoft.UI.Xaml.UIElement, IntPtr, global::Microsoft.UI.Xaml.Input.LosingFocusEventArgs, IntPtr>.Abi_Invoke(thisPtr, global::ABI.Microsoft.UI.Xaml.UIElement.FromAbi(sender), global::ABI.Microsoft.UI.Xaml.Input.LosingFocusEventArgs.FromAbi(args)); } catch (Exception __exception__) { global::WinRT.ExceptionHelpers.SetErrorInfo(__exception__); return global::WinRT.ExceptionHelpers.GetHRForException(__exception__); } return 0; } // ... }
- ViewModel值被清空阶段:紧接着,ViewModel.Value的setter会被触发——这个断点无法通过单步调试到达,只能单独设置断点才能捕获到。此时传入的赋值是空字符串,而且调用栈里能看到刚才那段生成代码的调用记录。
- LostFocus事件阶段:跳出生成函数后,AutoSuggestBox触发
LostFocus事件,此时再检查就会发现控件的Text和ViewModel的Value都已经变成空字符串了。
我已经尝试过的排查方法
我试过移除这个AutoSuggestBox上所有的事件处理方法、自定义样式,以及任何可能影响它的配置项;另外也把项目中所有可能修改ViewModel.Value的代码都逐一删除了,但不管怎么调整,问题依然存在。这个bug已经困扰我快一个月了,实在找不到突破口,希望能得到大家的帮助。
备注:内容来源于stack exchange,提问作者Josh Brunton




