我这里有一个非常简单的场景。看看布局,请:
<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>
和codebehind:
private void _datePicker_OnLostFocus(object sender, RoutedEventArgs e)
{
Debug.WriteLine("LostFocuse");
}
所以,麻烦的是当我拿到一些日期并点击TextBox
然后,事件LostFocus
会触发7(七!)次。 DatePicker
TextBox
在我LostKeyBoardFocus
上完全失去焦点并且完全剩下6次时,我真的无法解释。
我该如何解决?我只需要一次这次活动。或者我可以使用其他一些活动?我尝试了{{1}}同样的结果。
答案 0 :(得分:5)
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");
}
}
答案 1 :(得分:1)
您可以添加bool值以首次检查,然后将e.Handled设置为true。
bool isFired = false;
private void _datePicker_OnLostFocus(object sender, RoutedEventArgs e)
{
if (!isFired)
{
isFired = true;
}
e.Handled = true;
}
答案 2 :(得分:1)
您已经描述了UIElement.LostFocus
event的正常.NET行为。从MSDN上的链接页面:
当此元素失去逻辑焦点时发生。
注意它说逻辑焦点... WPF有两种焦点;逻辑和键盘。再次从链接页面:
逻辑焦点与键盘焦点的不同之处在于,如果使用方法调用故意强制取消焦点,但之前的键盘焦点位于不同的范围内。在这种情况下,键盘焦点保持原样,并且调用Focus方法的元素仍然是逻辑焦点。
最后,为什么这个事件会被提升很多次?这是因为DatePicker
中的偶数子元素可以在单击时删除它的逻辑焦点,并且当焦点移动到各种内部控件时,它可以快速连续几次返回DatePicker
。再一次,来自链接页面:
因为此事件使用冒泡路由,所以失去焦点的元素可能是子元素,而不是实际附加事件处理程序的元素。