WPF DatePicker LostFocus触发七次

时间:2014-08-06 12:29:48

标签: c# wpf datepicker lost-focus

我这里有一个非常简单的场景。看看布局,请:

<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}}同样的结果。

3 个答案:

答案 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。再一次,来自链接页面:

  

因为此事件使用冒泡路由,所以失去焦点的元素可能是子元素,而不是实际附加事件处理程序的元素。