0

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

在它的正下方,我有一个占据整个屏幕宽度的内容控件。

内容控件将根据突出显示的菜单项更改加载的用户控件。所有用户控件均以以下形式设置

<Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="0" />
        <Grid Grid.Column="1" />
    </Grid>
</Grid>

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

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

我想我可以在我的视图模型中做到这一点,但我有很多页面都遇到了类似的问题,所以希望有一个比完全重写和控制所有键盘导航更简单的解决方案。

任何帮助将不胜感激。

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

4

1 回答 1

0

这个问题没有答案,所以我会发布我的解决方案。我仍然对它不满意,因为它似乎有点 hack,但直到出现更好的东西.....如上所述,键盘导航似乎可以在它周围使用网格,但我不希望网格有重点。我所做的是创建一个扩展网格的自定义控件。我覆盖获取键盘焦点,然后查看最后具有焦点的 uielement 并检查它是否在网格之外(即我正在导航到网格中)。如果是这样的话,那么我看看焦点可能来自哪个方向。我说可能是因为 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);
    }        
于 2012-05-15T00:05:51.390 回答