开发者

Is there a way to make LostFocus fire when the keyboard focus leaves a focus scope?

My application's building a UI dynamically in which each ItemsControl in the view is a focus scope. The items displayed by each ItemsControl are controls in its focus scope. The user can tab through all of the controls in the view from start to end (i.e. the keyboard navigation mode is Continue). These controls are all bound to data source properties.

What seems to be happening is that when I'm on the last control in the first focus开发者_如何学Go scope and press TAB, the keyboard focus moves to the second focus scope, but the previous control doesn't lose logical focus. So the bound property doesn't get updated.

I can make this problem go away (in theory, at least) by not making each ItemsControl a focus scope. But I didn't decide to implement logical focus capriciously: there are things the application needs to do when each ItemsControl loses logical focus, and if I get rid of the focus scopes it's going to be hard to make that happen.

This seems like a problem that should have a straightforward solution, but nothing in the documentation seems to suggest a way around it. Any ideas?


The problem is that you're trying to make logical focus in-line with keyboard focus which as the documentation shows is really not how it is supposed to be used. Logical focus provides a way to maintain what the previous control that had focus in a given focus scope so you can refocus again on it when you regain keyboard focus.

Looking at your question I think what you really want to do is pick up the event when your item contol, or one of the visual child elements, loses keyboard focus. This can be achieved using IsKeyboardFocusedWithin property and you can trigger actions based on the associated event.

If you need this to be a routed event, then you'll need a custom control like follows which exposes a routing event for gaining and losing focus.

public partial class FocusManagingControl : UserControl
{
    public static readonly RoutedEvent KeyboardLostFocusWithinEvent = EventManager.RegisterRoutedEvent("KeyboardLostFocusWithin", 
        RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(FocusManagingControl));

    public static readonly RoutedEvent KeyboardGotFocusWithinEvent = EventManager.RegisterRoutedEvent("KeyboardGotFocusWithin", 
        RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(FocusManagingControl));

    public event RoutedEventHandler KeyboardLostFocusWithin 
    {
        add { AddHandler(KeyboardLostFocusWithinEvent, value); }
        remove { RemoveHandler(KeyboardLostFocusWithinEvent, value); }
    }

    public event RoutedEventHandler KeyboardGotFocusWithin 
    {
        add { AddHandler(KeyboardGotFocusWithinEvent, value); }
        remove { RemoveHandler(KeyboardGotFocusWithinEvent, value); }
    }

    public FocusManagingControl()
    {
        this.InitializeComponent();
        this.IsKeyboardFocusWithinChanged += FocusManagingControl_IsKeyboardFocusWithinChanged;
    }

    private void FocusManagingControl_IsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if((bool)e.OldValue && !(bool)e.NewValue)
            RaiseEvent(new RoutedEventArgs(KeyboardLostFocusWithinEvent, this));

        if(!(bool)e.OldValue && (bool)e.NewValue)
            RaiseEvent(new RoutedEventArgs(KeyboardGotFocusWithinEvent, this));
    }
}

Which you can use in your XAML with the entry

<local:FocusManagingControl>
        <local:FocusManagingControl.Triggers>
            <EventTrigger RoutedEvent="local:FocusManagingControl.KeyboardLostFocusWithin">                
            ....
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜