WPF DatePicker LostFocus触发七次
本文关键字:七次 DatePicker LostFocus WPF | 更新日期: 2023-09-27 18:16:34
我这里有一个非常简单的场景。请看一下布局:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBox Grid.Row="0"></TextBox>
<DatePicker Grid.Row="1"
Name="_datePicker"
LostFocus="_datePicker_OnLostFocus"></DatePicker>
</Grid>
后台代码:和
private void _datePicker_OnLostFocus(object sender, RoutedEventArgs e)
{
Debug.WriteLine("LostFocuse");
}
所以,问题是当我拿起一些日期并单击TextBox
时,事件LostFocus
触发7次( 7 !)。有一次DatePicker
真的失去了焦点,当我点击TextBox
时,剩下的六次完全无法解释。
我该如何修复它?我只需要一个触发此事件。或者我可以用其他事件?我尝试了LostKeyBoardFocus
与相同的结果。
LostFocus是路由策略设置为 Bubble
的路由事件。冒泡意味着它将冒泡到父窗口直到根窗口,直到通过显式设置 e.Handled = true;
在某处处理。
所以,这意味着即使当子控件失去焦点时它也会冒泡到你的datePicker上这就是为什么你会看到多个点击到你的方法
您可以检查属性 IsKeyboardFocusWithin
,如果焦点在您的控制范围内,则返回。由于您对侦听子丢失焦点事件不感兴趣,您可以像这样检查处理程序中的此属性,并仅在实际焦点被datePicker丢失时执行代码:
private void _datePicker_OnLostFocus(object sender, RoutedEventArgs e)
{
DatePicker picker = sender as DatePicker;
if (!picker.IsKeyboardFocusWithin)
{
System.Diagnostics.Debug.WriteLine("LostFocuse");
}
}
您可以添加一个bool值用于第一次检查,然后将e.Handled设置为true。
bool isFired = false;
private void _datePicker_OnLostFocus(object sender, RoutedEventArgs e)
{
if (!isFired)
{
isFired = true;
}
e.Handled = true;
}
您已经描述了UIElement.LostFocus
事件的正常. net行为。从MSDN上的链接页面:
当此元素失去逻辑焦点时发生。
注意它说logical focus…WPF有两种焦点;逻辑和键盘。再次从链接页面:
逻辑焦点与键盘焦点不同,如果焦点是通过使用方法调用故意强制转移的,但之前的键盘焦点存在于不同的作用域中。在这个场景中,键盘焦点保持在原来的位置,而调用focus方法的元素仍然获得逻辑焦点。
最后,为什么事件被提出了这么多次?这是因为即使是DatePicker
中的子元素也可以在单击它们时从中移除逻辑焦点,并且当焦点通过各种内部控制移动时,它可以快速连续多次返回DatePicker
。再一次,从链接页面:
因为该事件使用冒泡路由,所以失去焦点的元素可能是一个子元素,而不是实际附加了事件处理程序的元素。