WPF:关注关键事件
WPF: Focus on keyevents
在我的 "real" 解决方案中,我有一个文本框,当用户按下(文本框为空)时,焦点必须转移到另一个控件。
如果我在 "another control" 上按 "down-arrow",我必须聚焦文本框,但现在文本框捕获相同的 "down" 事件并将焦点设置到另一个控件。
让我用一个例子展示一下....
<Window x:Class="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:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,10,0,0"/>
<Button x:Name="button2" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,10,0,0"/>
<Button x:Name="button3" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,10,0,0"/>
</StackPanel>
</Grid>
</Window>
Class MainWindow
Private Sub textBox_PreviewKeyUp(sender As Object, e As KeyEventArgs) Handles textBox.PreviewKeyUp
If Me.textBox.Text = "" AndAlso e.Key = Key.Down Then
Me.button1.Focus()
End If
End Sub
Private Sub button2_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles button2.PreviewKeyDown
e.Handled = True
Me.textBox.Focus()
End Sub
End Class
这是我想要它做的...
- 手动将焦点设置在文本框上
- 按 "arrow-down" 转到 Button1
- 按"arrow-down"转到Button2
- 按 "arrow-down" 转到文本框
- 什么都不做
实际情况如下...
- 手动将焦点设置在文本框上
- 按 "arrow-down" 转到 Button1
- 按"arrow-down"转到Button2
- 按 "arrow-down" 转到文本框
- 焦点自动移动到 Button1
然后我想到了使用KeyUp事件...
Private Sub button2_PreviewKeyUp(sender As Object, e As KeyEventArgs) Handles button2.PreviewKeyUp
e.Handled = True
Me.textBox.Focus()
End Sub
...但是我无法将焦点移至 Button2。
我不能在TextBox上使用KeyDown,因为我需要检查文本框的内容,而且它只能在KeyUp事件中使用。
我知道这很简单,但我一直盯着自己看。
求助:)
这肯定是一个有趣的情况。
这里的主要问题是向下箭头已经用于某些控件(如按钮)之间的导航。那么会发生什么是按钮在 KeyDown 事件上执行默认焦点切换,然后您的事件处理程序对 KeyUp 起作用 - 但焦点已经移动!
所以要解决这个问题,我们需要使用默认导航,而不是反对它。
首先,对于按钮:没有手动事件处理。此外,我们需要通过 IsTabStop
属性 从 Tab 键顺序中删除最后一个。并且不要让焦点离开我们的 StackPanel KeyboardNavigation.DirectionalNavigation:
<StackPanel KeyboardNavigation.DirectionalNavigation="Cycle">
<TextBox x:Name="textBox" Text="" PreviewKeyDown="textBox_PreviewKeyDown" />
<Button x:Name="button1" Content="Button" />
<Button x:Name="button2" Content="Button" />
<Button x:Name="button3" Content="Button" IsTabStop="False" />
</StackPanel>
然后,文本框。我们需要切换到 KeyDown
否则它会遇到同样的问题。这对我们来说无关紧要,因为我们真正检查内容的唯一时间是按下向下箭头(它不会更改文本,对吗?)。但是我们需要将事件标记为已处理以停止它:
Private Sub textBox_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles textBox.PreviewKeyDown
If Me.textBox.Text = "" AndAlso e.Key = Key.Down Then
e.Handled = True
Me.button1.Focus()
End If
End Sub
在我的 "real" 解决方案中,我有一个文本框,当用户按下(文本框为空)时,焦点必须转移到另一个控件。
如果我在 "another control" 上按 "down-arrow",我必须聚焦文本框,但现在文本框捕获相同的 "down" 事件并将焦点设置到另一个控件。
让我用一个例子展示一下....
<Window x:Class="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:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,10,0,0"/>
<Button x:Name="button2" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,10,0,0"/>
<Button x:Name="button3" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,10,0,0"/>
</StackPanel>
</Grid>
</Window>
Class MainWindow
Private Sub textBox_PreviewKeyUp(sender As Object, e As KeyEventArgs) Handles textBox.PreviewKeyUp
If Me.textBox.Text = "" AndAlso e.Key = Key.Down Then
Me.button1.Focus()
End If
End Sub
Private Sub button2_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles button2.PreviewKeyDown
e.Handled = True
Me.textBox.Focus()
End Sub
End Class
这是我想要它做的...
- 手动将焦点设置在文本框上
- 按 "arrow-down" 转到 Button1
- 按"arrow-down"转到Button2
- 按 "arrow-down" 转到文本框
- 什么都不做
实际情况如下...
- 手动将焦点设置在文本框上
- 按 "arrow-down" 转到 Button1
- 按"arrow-down"转到Button2
- 按 "arrow-down" 转到文本框
- 焦点自动移动到 Button1
然后我想到了使用KeyUp事件...
Private Sub button2_PreviewKeyUp(sender As Object, e As KeyEventArgs) Handles button2.PreviewKeyUp
e.Handled = True
Me.textBox.Focus()
End Sub
...但是我无法将焦点移至 Button2。
我不能在TextBox上使用KeyDown,因为我需要检查文本框的内容,而且它只能在KeyUp事件中使用。
我知道这很简单,但我一直盯着自己看。
求助:)
这肯定是一个有趣的情况。 这里的主要问题是向下箭头已经用于某些控件(如按钮)之间的导航。那么会发生什么是按钮在 KeyDown 事件上执行默认焦点切换,然后您的事件处理程序对 KeyUp 起作用 - 但焦点已经移动!
所以要解决这个问题,我们需要使用默认导航,而不是反对它。
首先,对于按钮:没有手动事件处理。此外,我们需要通过 IsTabStop
属性 从 Tab 键顺序中删除最后一个。并且不要让焦点离开我们的 StackPanel KeyboardNavigation.DirectionalNavigation:
<StackPanel KeyboardNavigation.DirectionalNavigation="Cycle">
<TextBox x:Name="textBox" Text="" PreviewKeyDown="textBox_PreviewKeyDown" />
<Button x:Name="button1" Content="Button" />
<Button x:Name="button2" Content="Button" />
<Button x:Name="button3" Content="Button" IsTabStop="False" />
</StackPanel>
然后,文本框。我们需要切换到 KeyDown
否则它会遇到同样的问题。这对我们来说无关紧要,因为我们真正检查内容的唯一时间是按下向下箭头(它不会更改文本,对吗?)。但是我们需要将事件标记为已处理以停止它:
Private Sub textBox_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles textBox.PreviewKeyDown
If Me.textBox.Text = "" AndAlso e.Key = Key.Down Then
e.Handled = True
Me.button1.Focus()
End If
End Sub