需要能够退出Alt键下划线模式,可能使用ESC键

Kev*_*ski 6 wpf keyboard-shortcuts

问题:按下并释放Alt键后,如何退出键盘热键模式?在Office中的ESC作品,在WPF中它没有.

详细信息:Label在WPF应用程序中有各种元素.

<StackPanel>
    <Label Grid.Column="0" VerticalAlignment="Center" Content="_Textbox 1" Target="textbox1" />
    <TextBox x:Name="textbox1" Width="50" />
    <Label Grid.Column="0" VerticalAlignment="Center" Content="T_extbox 2" Target="textbox2" />
    <TextBox x:Name="textbox2" Width="50" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

当我按下并释放Alt键时,P保持下划线,然后我可以单独按下P键,Label就会采取行动.这与Word 2013和Notepad的工作方式相同,因为您无需同时按AltP.

WPF不同的地方是我不能ESC按键来停止下划线并停止自动导航到Label控件.我看到退出键盘导航模式的唯一方法是使用鼠标并单击某处,从而击败键盘导航的目标.

Viv*_*Viv 0

添加到我原来的评论

实际上,记事本和 Word 2013 的行为略有不同。带有热键的控件位于菜单中,一旦您按 Alt,您就会获得焦点,您可以看到它们获得焦点,因为文本区域插入符号丢失,然后 Esc 将焦点返回到文本框,同时清除“_”。现在,在示例代码中,如果将两个标签或什至一个标签放入 a 中,然后按 Alt,您将获得与 Word 或记事本相同的行为。如果没有菜单,就没有控件想要获得中间焦点。

这似乎是一个问题,在它自己的FocusManager.IsFocusScopeMenu中获得延迟焦点来处理这些热键。

MSDN的另一个片段:

以下方案说明了 Windows Presentation Foundation (WPF) 应用程序中键盘焦点和逻辑焦点如何更改,该应用程序具有带 TextBox 的 Window 和带 MenuItem 的 Menu。当键盘焦点从 TextBox 更改为 MenuItem 时,TextBox 会失去键盘焦点,但会保留 Window 焦点范围的逻辑焦点。MenuItem 获取键盘焦点并获取 Menu 焦点范围的逻辑焦点。当键盘焦点返回到根Window时,Window焦点范围内具有逻辑焦点的元素将获得键盘焦点,在本例中为TextBox。TextBox 现在具有键盘焦点和逻辑焦点。MenuItem 失去键盘焦点,但保留菜单焦点范围的逻辑焦点。

解决方案:

Menu如果您无法忍受实现热键功能所施加的分组要求的限制,您可以执行以下操作:

<Grid Margin="25">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="15" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <!-- cannot use Visibility="Collapsed" or "Hidden" on the Menu to make it take focus on Alt press --> 
  <Menu Width="0"
        Height="0">
    <Label x:Name="label1"
            Content="_Textbox 1"
            Target="{Binding ElementName=textbox1}" />
    <Label x:Name="label2"
            Content="T_extbox 2"
            Target="{Binding ElementName=textbox2}" />
    <Label x:Name="label3"
            Content="Another Loose Label to Link Text_Box 1"
            Target="{Binding ElementName=textbox1}" />
  </Menu>
  <Label Grid.Row="0"
          Grid.Column="0"
          Content="{Binding ElementName=label1,
                            Path=Content}" />
  <TextBox x:Name="textbox1"
            Grid.Row="0"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            Margin="15 0 0 0"
            VerticalAlignment="Center" />
  <Label Grid.Row="2"
          Grid.Column="0"
          Content="{Binding ElementName=label2,
                            Path=Content}" />
  <TextBox x:Name="textbox2"
            Grid.Row="2"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            Margin="15 0 0 0"
            VerticalAlignment="Center" />
  <Rectangle Grid.Row="3"
              Grid.RowSpan="2"
              Grid.Column="1"
              Margin="10"
              Fill="Tomato" />
  <Label Grid.Row="4"
          Grid.Column="2"
          Content="{Binding ElementName=label3,
                            Path=Content}" />
</Grid>
Run Code Online (Sandbox Code Playgroud)

因此,在此设置中,我们不Style为任何控件使用任何自定义。我们几乎创建了一个新的顶层Menu,并向其中添加所有所需的热键Label,并将其宽度和高度设置为 0。

因此,在实际的可见Grid布局中,我们可以将可见的位置放置Label在我们选择的任何位置,并且为了避免Label.Content为每个指定两次Label(在菜单中一次,在实际布局中的下一个)时重复代码,我们使用绑定来获取视觉标签的内容从菜单中相应的标签。

更新

回复OP的评论:

我不确定这在我的应用程序中是否实用。我的应用程序中到处都有热键,其中一些热键在屏幕间是重复的。实施这种类型的解决方法是不可维护的。

好吧,我不明白重复或到处都是东西对这个问题有什么影响。

  • Window如果您在多个'中有重复的热键,则将Content这些重复的项目定义为Stringxaml 或 .resx 中的资源,您可以在任何需要的地方引用它。
  • 可维护性——好吧,你没有为可维护性做任何特别的事情。您的布局不会受到影响,您不会受到任何限制。如果您有任何隐藏在每个定义热键的<Menu>顶层,并且在该窗口中任何需要该功能的控件都绑定到相应的菜单子项。我认为它将热键的范围统一到一个地方,而不是多个不同地方。WindowWindowWindow

最后,我并不是想把这种方法强加给你,这取决于你的个人喜好。如果您对此感到不舒服,那么您可以对您的Label进行子分类并自己实现延迟焦点的功能,或者提出 Microsoft 错误,看看他们是否可以为您解决该问题或找到替代解决方案或放弃热门-关键功能全部放在一起。