wpf 如何防止选项卡导航到控件,同时允许定向导航到该控件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27325474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:46:23  来源:igfitidea点击:

How to prevent tab navigation to a control, while allowing directional navigation to that control

wpffocustabbingkeyboard-navigation

提问by Matt Jacobi

In WPF (MVVM, no code-behind), say I have the following xaml:

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

By default, you can (1) tab between the buttons or (2) up/down arrow between the buttons. I want to make one of the buttons -- the Specialbutton -- notfocusable via tab, yet still focusable via up/down. I tried IsTabStop="False", but that also prevents focusing that button via directional navigation (up/down arrows).

默认情况下,您可以 (1) 按钮之间的 Tab 键或 (2) 按钮之间的向上/向下箭头。我想使按钮之一-特殊按钮-通过选项卡可聚焦,通过了但仍然可聚焦/向下。我试过了IsTabStop="False",但这也阻止了通过定向导航(向上/向下箭头)聚焦该按钮。

How can I remove a single button from tab navigation, while continuing to allow directional navigation? Tabbing and arrowing should be unaffected for all other controls.

如何从选项卡导航中删除单个按钮,同时继续允许定向导航对于所有其他控件,标签和箭头应该不受影响

I've tried combinations of IsTabStop, KeyboardNavigation.TabNavigation, and KeyboardNavigation.DirectionalNavigationto no avail. Maybe I haven't found the right mix. Or maybe there is another approach. Ideas?

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



EDIT: Okay, I am adding a bounty. To be clear, I am looking for a MVVM, no code-behind way to decorate a control (e.g. via style, attached property, attached behavior, etc), such that it is removed from the tab order, while remaining a valid directional navigation target. Hard coding knowledge of the controls into the Window (or similar), is not acceptable. This needs to be a general, reusable solution. Something like: <Button AllowDirectionalNavigationButPreventTabNavigation="True"/>.

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

回答by Nick Sologoub

How about that option. You stick your special button into another container and put KeyboardNavigation.TabNavigation="None" on that container. I've just tried it and it looks like I can achieve what you need.

那个选项怎么样。您将您的特殊按钮粘贴到另一个容器中,并将 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>

回答by ELH

here how i did it :

我是如何做到的:

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

i am using the mvvmlight, and the EventToCommand is used to intercept the KeyDown Event and direct it to the following command in the ViewModel:

我正在使用 mvvmlight,EventToCommand 用于拦截 KeyDown 事件并将其定向到 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;
                    }
                }));
        }
    }