问题
I have very simple scenario here. Look at layout, please:
<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>
and codebehind:
private void _datePicker_OnLostFocus(object sender, RoutedEventArgs e)
{
Debug.WriteLine("LostFocuse");
}
So, trouble is when I pick up some date and click TextBox
then, event LostFocus
fires 7 (seven!) times. One when DatePicker
really lost focus when I ckicked on TextBox
and remaining six times totally are not explainable for me.
How can I fix it? I need only one fireing of this event. Or may be I can use some other event? I tried LostKeyBoardFocus
with the same result.
回答1:
LostFocus is a routed event with route strategy set to Bubble
. By bubble it means it will bubble upto its parent till root window until handled somewhere by explicitly setting e.Handled = true;
.
So, that means even when child control loose focus it will bubble up to your datePicker that's why you see multiple hits to your method.
You can check for property IsKeyboardFocusWithin
which returns if focus is within your control. Since you are not interested in listening to child lost focus event, you can check for this property in your handler like this and execute your code only when actual focus is lost by datePicker:
private void _datePicker_OnLostFocus(object sender, RoutedEventArgs e)
{
DatePicker picker = sender as DatePicker;
if (!picker.IsKeyboardFocusWithin)
{
System.Diagnostics.Debug.WriteLine("LostFocuse");
}
}
回答2:
You could add a bool value to check for the first time and then set e.Handled to be true.
bool isFired = false;
private void _datePicker_OnLostFocus(object sender, RoutedEventArgs e)
{
if (!isFired)
{
isFired = true;
}
e.Handled = true;
}
回答3:
You have described the is the normal .NET behaviour of the UIElement.LostFocus event. From the linked page on MSDN:
Occurs when this element loses logical focus.
Note that it says logical focus... WPF has two kinds of focus; logical and keyboard. Again from the linked page:
Logical focus differs from keyboard focus if focus is deliberately forced away by using a method call but the previous keyboard focus exists in a different scope. In this scenario, keyboard focus remains where it is, and the element where a Focus method is called still gets logical focus.
Finally, why did the event get raised so many times? It is because even child elements within the DatePicker
can remove the logical focus from it as they are clicked on and it can return to the DatePicker
several times in quick succession as focus moves through the various internal controls. Once more, from the linked page:
Because this event uses bubbling routing, the element that loses focus might be a child element instead of the element where the event handler is actually attached.
来源:https://stackoverflow.com/questions/25160459/wpf-datepicker-lostfocus-fires-seven-times