wpf键盘导航行为

时间:2012-05-04 13:28:37

标签: wpf grid keyboard-navigation

我在wpf应用程序中遇到键盘导航问题。 简化我有一个水平堆栈面板,其中包含一个菜单项列表,占据了屏幕宽度的四分之一。

直接在我之下,我有一个内容控件,它占据了屏幕的整个宽度。

内容控件将根据突出显示的菜单项更改加载的用户控件。所有用户控件都以

的形式设置
<Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="0" />
        <Grid Grid.Column="1" />
    </Grid>
</Grid>

问题在于,当我从堆叠面板按下向下键时,它会尝试将焦点放在其正下方的内部网格列上。第一列包含可聚焦项目,但第二列不包含。 这适用于stackpanel中直接位于第一列上方的前几个菜单项,但最终我得到直接位于第二列的菜单项,此时我无法向下导航。

我添加了外部网格,如上面的xaml所示,但这没有帮助。为什么焦点不会移动到网格(或内部网格)中可用的第一个可聚焦元素,如何将焦点强制放入第1列?

我想我可以在我的viewmodel中执行此操作但是我有大量页面都遇到类似的问题所以希望有一个更简单的解决方案,而不是完全重写和控制所有键盘导航。

非常感谢任何帮助。

更新:如果我在第一个网格上将focuasable设置为true,则导航工作并最终在第1列中显示,但显然第一次按下按键“出现”无效,因为焦点正在给予网格。我想要一个类似的行为,但导航将网格直接跳到第1列。

1 个答案:

答案 0 :(得分:0)

这个问题没有答案,所以我会发布我的解决方案。我仍然不满意它,因为它看起来有点像黑客,但直到更好的东西出现..... 如上所述,键盘导航似乎与它周围的网格一起使用,但我不希望网格具有焦点。 我所做的是创建一个扩展网格的自定义控件。 我重写获得键盘焦点,然后查看最后有焦点的元素并检查它是否在网格之外(I.E我正在导航到网格中)。 如果是这种情况,那么我会看看焦点可能来自哪个方向。我说可能是PredictFocus可能来自一个向上和一个左键按下,这就是为什么我认为这个解决方案有点hacky。 如果找到方向,那么我只需再次朝那个方向移动焦点。为了实现这一点,必须在网格上具有可聚焦性。

protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
    {
        UIElement previousFocus = (UIElement)e.OldFocus;
        if (previousFocus != null)
        {
            if (!previousFocus.IsDescendantOf(this))
            {
                if (previousFocus.PredictFocus(FocusNavigationDirection.Up).Equals(this))
                {
                    this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Up));
                }
                else if (previousFocus.PredictFocus(FocusNavigationDirection.Down).Equals(this))
                {
                    this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
                }
                else if (previousFocus.PredictFocus(FocusNavigationDirection.Left).Equals(this))
                {
                    this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Left));
                }
                else if (previousFocus.PredictFocus(FocusNavigationDirection.Right).Equals(this))
                {
                    this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right));
                }
            }
        }
        base.OnGotKeyboardFocus(e);
    }