当键盘焦点离开焦点范围时,有没有办法让 LostFocus 触发?

发布于 2024-12-05 13:42:37 字数 470 浏览 1 评论 0原文

我的应用程序动态构建一个 UI,其中视图中的每个 ItemsControl 都是焦点范围。每个 ItemsControl 显示的项目是其焦点范围内的控件。用户可以从头到尾浏览视图中的所有控件(即键盘导航模式为Continue)。这些控件都绑定到数据源属性。

似乎发生的情况是,当我在第一个焦点范围中的最后一个控件上并按 TAB 时,键盘焦点移动到第二个焦点范围,但前一个控件不会失去逻辑焦点。所以绑定的属性不会更新。

我可以通过不让每个 ItemsControl 成为焦点范围来解决这个问题(至少在理论上)。但我并没有决定随意实现逻辑焦点:当每个 ItemsControl 失去逻辑焦点时,应用程序需要执行一些操作,如果我摆脱焦点范围,它将很难做到那会发生。

这似乎是一个应该有一个简单解决方案的问题,但文档中似乎没有任何建议解决它。有什么想法吗?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月依秋水 2024-12-12 13:42:37

问题是您试图将 逻辑焦点 - 与 键盘focus 正如文档所示,这实际上并不是它应该如何使用。逻辑焦点提供了一种方法来维持先前在给定焦点范围内获得焦点的控件,以便您在重新获得键盘焦点时可以再次重新聚焦它。

看看你的问题,我认为你真正想做的是当你的项目控件或视觉子元素之一失去键盘焦点时拾取事件。这个可以
使用 IsKeyboardFocusedWithin 属性来实现,您可以触发基于关联的 事件

如果您需要将其作为路由事件,那么您需要如下所示的自定义控件公开了用于获得和失去焦点的路由事件。

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));
    }
}

您可以在 XAML 中将其与条目一起使用

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

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">                
            ....
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文