【问题标题】:How to prevent tab navigation to a control, while allowing directional navigation to that control如何防止选项卡导航到控件,同时允许定向导航到该控件
【发布时间】:2014-12-05 22:09:16
【问题描述】:

在 WPF(MVVM,无代码隐藏)中,假设我有以下 xaml:

<StackPanel>
    <Button>Normal 1</Button>
    <Button>Special</Button> <!--This button should not tab focus, but still focus via arrow keys-->
    <Button>Normal 2</Button>
</StackPanel>

默认情况下,您可以 (1) 按钮之间的制表符或 (2) 按钮之间的向上/向下箭头。我想让其中一个按钮 - Special 按钮 - not 可通过选项卡聚焦,但仍可通过向上/向下聚焦。我试过IsTabStop="False",但这也阻止了通过定向导航(上/下箭头)聚焦该按钮。

如何从标签导航中删除单个按钮,同时继续允许定向导航?制表符和箭头应该不影响所有其他控件

我尝试了 IsTabStopKeyboardNavigation.TabNavigationKeyboardNavigation.DirectionalNavigation 的组合,但无济于事。也许我还没有找到合适的组合。或者也许还有另一种方法。想法?


编辑:好的,我正在添加赏金。需要明确的是,我正在寻找一个 MVVM,没有代码隐藏方式来装饰控件(例如,通过样式、附加属性、附加行为等),以便将其从选项卡顺序中删除,同时保持有效的方向导航目标。将控件硬编码到窗口(或类似)中是不可接受的。这需要一个通用的、可重用的解决方案。比如:&lt;Button AllowDirectionalNavigationButPreventTabNavigation="True"/&gt;

【问题讨论】:

  • 这应该会有所帮助:[WPF:如何在不禁用箭头键导航的情况下禁用标签导航?][1] [1]:stackoverflow.com/questions/4210659/…
  • @Joseph 我发现了这个问题,但是那个人有不同的情况(他们使用的是列表视图),并且建议的解决方案都没有解决我的确切问题。另外,公认的解决方案使用代码隐藏,并要求窗口了解其中所有控件的选项卡行为——我希望控件决定它自己的行为。

标签: wpf focus tabbing keyboard-navigation


【解决方案1】:

那个选项怎么样。您将特殊按钮粘贴到另一个容器中,然后将 KeyboardNavigation.TabNavigation="None" 放在该容器上。我刚刚试了一下,看来我可以达到你所需要的。

<StackPanel >
  <Button>Normal 1</Button>
  <StackPanel KeyboardNavigation.TabNavigation="None">
    <Button>Special</Button><!--This button should not tab focus, but still focus via arrow keys-->
  </StackPanel>
  <Button>Normal 2</Button>
</StackPanel>

【讨论】:

  • 这是正确的解决方案; TabNavigation 属性控制元素的 children 的逻辑导航行为,因此在 OP 的情况下,“特殊”按钮应该包装在另一个容器中。
  • 完美!我的真实情况更复杂,但这是我需要的想法/信息。在我的自定义控件样式中,我设置了Focusable=FalseKeyboardNavigation.TabNavigation=None。然后,在自定义控件的控件模板中,我设置了Focusable=True,它就达到了我想要的效果。
  • 如果您对包含在 Grid 中的按钮执行此操作,乍一看它是有效的。但是如果你点击按钮,焦点仍然会回到按钮上(我使用的是 MaterialDesignToolkit)。有什么想法可以结束这个问题吗?
【解决方案2】:

我是怎么做到的:

<Window x:Class="MvvmLight1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ignore="http://www.ignore.com"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:command="http://www.galasoft.ch/mvvmlight"
    mc:Ignorable="d ignore"
    Height="300"
    Width="300"
    DataContext="{Binding Main, Source={StaticResource Locator}}">
<i:Interaction.Triggers>
    <i:EventTrigger EventName="KeyDown">
        <command:EventToCommand Command="{Binding Mode=OneWay,Path=KeyDownCommand}" PassEventArgsToCommand="True"/>
    </i:EventTrigger>
</i:Interaction.Triggers>
<Grid x:Name="LayoutRoot">
    <StackPanel>
        <Button>Normal 1</Button>
        <Button>Special</Button>
        <!--Should not tab focus, yet still focus via arrow keys-->
        <Button>Normal 2</Button>
    </StackPanel>
</Grid>

我用的是mvvmlight,EventToCommand用来拦截KeyDown Event,并把它定向到ViewModel中的如下命令:

 private RelayCommand<KeyEventArgs> _keyDownCommand;
    public RelayCommand<KeyEventArgs> KeyDownCommand
    {
        get
        {
            return _keyDownCommand
                ?? (_keyDownCommand = new RelayCommand<KeyEventArgs>(
                (s) =>
                {
                    if (s.Key == Key.Tab)
                    {
                        s.Handled = true;
                    }
                }));
        }
    }

【讨论】:

  • 谢谢,但这会禁用整个窗口的选项卡。我正在寻找一种只为一个控件禁用选项卡的方法。
  • 什么控制!你是说 StackPanel 吗?
  • 只需一个按钮。特殊按钮。所有其他按钮仍应为可选项卡。问题是:如何从标签顺序中删除控件(例如按钮),同时将其保留为有效的方向导航目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-09
相关资源
最近更新 更多