3

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

<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(七!)次。一个当DatePicker我开始时真的失去焦点的时候TextBox并且完全剩下六次对我来说是无法解释的。

我该如何解决?我只需要触发一次此事件。或者我可以使用其他活动吗?我尝试LostKeyBoardFocus了相同的结果。

4

3 回答 3

6

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");
    }
}
于 2014-08-06T13:49:12.613 回答
1

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;

}
于 2014-08-06T12:33:50.370 回答
1

您已经描述了UIElement.LostFocus事件的正常 .NET 行为。从 MSDN 上的链接页面:

当此元素失去逻辑焦点时发生。

请注意,它说的是逻辑焦点... WPF 有两种焦点;逻辑和键盘。再次从链接页面:

如果通过使用方法调用故意强制离开焦点但先前的键盘焦点存在于不同的范围内,则逻辑焦点不同于键盘焦点。在这种情况下,键盘焦点保持在原处,调用 Focus 方法的元素仍然获得逻辑焦点。

最后,为什么这个事件会被提出这么多次?这是因为即使是其中的子元素DatePicker也可以在单击它们时从中删除逻辑焦点,并且DatePicker随着焦点通过各种内部控件移动,它可以快速连续返回几次。再一次,从链接页面:

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

于 2014-08-06T12:48:04.080 回答