6

Question: How do you exit keyboard hot-key mode after pressing and releasing the Alt key? In Office the ESC works, in WPF it does not.

Details: I have various Label elements in a WPF application.

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

When I press and release the Alt key the P stays underlined and I can then separately press the P key and that Label takes its action. This is the same as how Word 2013 and Notepad work in that you don't have to press the Alt and the P at the same time.

Where WPF differs is I cannot press the ESC key to stop the underlining and stop the auto-navigation to Label controls. The only way I see to get out of keyboard navigation mode is to use the mouse and click somewhere, defeating the goal of keyboard navigation.

4

1 回答 1

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 焦点范围的逻辑焦点。

解决方案:

如果您无法忍受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>

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

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

更新

回复 OP 的评论:

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

好吧,我看不出重复或到处都是东西对这个 tbh 有什么影响。

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

最后,我不是想把这种方法强加给你,它归结为你的个人喜好。如果您对它感到不舒服,那么您可以将您Label的 's 子类化并自己实现延迟焦点的功能或提出 Microsoft 错误以查看他们是否可以为您解决它或找到替代解决方案或放开热门 -关键功能齐头并进。

于 2013-07-09T16:26:39.883 回答