WPF DatePicker LostFocus fires seven times

為{幸葍}努か 提交于 2019-12-23 20:56:24

问题


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 DatePickerreally 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!