奇怪的键盘焦点事件顺序
Weird keyboard focus event order
奇怪的 WPF 组合框行为:
我刚刚注意到,在 WPF ComboBox
中,当通过 Tab 键设置键盘焦点时(来自上一个控件的 Tab 键焦点),TextBox
在 ComboBox
("PART_EditableTextBox
") 是隧道事件的来源 OnPreviewGotKeyboardFocus
.
但是由于某些奇怪的原因,如果通过在控件内单击鼠标获得焦点,那么 OnPreviewGotKeyboardFocus
会被调用两次:第一次,Source 是 ComboBox
本身;第二次,Source 是 ComboBox
本身;第二次,Source 又是 PART_EditableTextBox
.
我还注意到,当在 ComboBox
上将 Focusable 设置为 False 时,您仍然可以使用 Tab 键聚焦到它,但不能使用鼠标。
有谁知道为什么会出现这种奇怪的行为?
来自微软文档
The KeyboardNavigation class is responsible for implementing default keyboard focus navigation when one of the navigation keys is pressed. The navigation keys are: TAB, SHIFT+TAB, CTRL+TAB, CTRL+SHIFT+TAB, UPARROW, DOWNARROW, LEFTARROW, and RIGHTARROW keys.
The navigation behavior of a navigation container can be changed by
setting the attached KeyboardNavigation properties TabNavigation,
ControlTabNavigation, and DirectionalNavigation. These properties are
of type KeyboardNavigationMode and the possible values are Continue,
Local, Contained, Cycle, Once, and None. The default value is
Continue, which means the element is not a navigation container.
组合框本身就是一个导航容器。这意味着当您按下 Tab 键时,PART_EditableTextBox 的容器默认将 KeyBoardNavigationMode 设置为 Continue(这意味着焦点直接转到第一个非容器元素)。 click 事件的工作方式不同,因为您没有按下键盘键,此行为将被覆盖,并且该事件按 WPF 将在可视化树中找到的任何元素顺序启动。这样做是为了确保您可以在焦点到达文本框之前处理此事件以对您的控件进行操作。此外,您必须考虑到这是必要的,因为 WPF 无法准确知道您要单击的内容。这就是为什么他必须按顺序从组合框的每一层引发相同的事件(如果您单击扩展器,焦点将不会停留在 PART_EditableTextBox 内)。
简而言之,如果您要按 TAB 键,WPF 默认情况下知道将聚焦的最终元素是组合框内的文本框,这就是组合框本身不需要它来引发事件的原因。另一方面,如果您单击组合框,WPF 需要检查哪个元素最后将获得焦点,以及是否有一些操作必须在切换焦点之前完成。
关于Focusable 属性 最后,这个对于一个控件来说,表示该控件是否可以接收到焦点,也就是用户点击该控件后,该控件可以接收键盘输入。对于设计用于接受用户输入的控件,Focusable 通常设置为 true。可以接收键盘焦点的部分是文本框。因此,如果您在组合框内设置 Focusable = false,KeyboardNavigation class 会将焦点放在组合框上,而不是文本框上,因为它无法应用其默认行为
奇怪的 WPF 组合框行为:
我刚刚注意到,在 WPF ComboBox
中,当通过 Tab 键设置键盘焦点时(来自上一个控件的 Tab 键焦点),TextBox
在 ComboBox
("PART_EditableTextBox
") 是隧道事件的来源 OnPreviewGotKeyboardFocus
.
但是由于某些奇怪的原因,如果通过在控件内单击鼠标获得焦点,那么 OnPreviewGotKeyboardFocus
会被调用两次:第一次,Source 是 ComboBox
本身;第二次,Source 是 ComboBox
本身;第二次,Source 又是 PART_EditableTextBox
.
我还注意到,当在 ComboBox
上将 Focusable 设置为 False 时,您仍然可以使用 Tab 键聚焦到它,但不能使用鼠标。
有谁知道为什么会出现这种奇怪的行为?
来自微软文档
The KeyboardNavigation class is responsible for implementing default keyboard focus navigation when one of the navigation keys is pressed. The navigation keys are: TAB, SHIFT+TAB, CTRL+TAB, CTRL+SHIFT+TAB, UPARROW, DOWNARROW, LEFTARROW, and RIGHTARROW keys.
The navigation behavior of a navigation container can be changed by setting the attached KeyboardNavigation properties TabNavigation, ControlTabNavigation, and DirectionalNavigation. These properties are of type KeyboardNavigationMode and the possible values are Continue, Local, Contained, Cycle, Once, and None. The default value is Continue, which means the element is not a navigation container.
组合框本身就是一个导航容器。这意味着当您按下 Tab 键时,PART_EditableTextBox 的容器默认将 KeyBoardNavigationMode 设置为 Continue(这意味着焦点直接转到第一个非容器元素)。 click 事件的工作方式不同,因为您没有按下键盘键,此行为将被覆盖,并且该事件按 WPF 将在可视化树中找到的任何元素顺序启动。这样做是为了确保您可以在焦点到达文本框之前处理此事件以对您的控件进行操作。此外,您必须考虑到这是必要的,因为 WPF 无法准确知道您要单击的内容。这就是为什么他必须按顺序从组合框的每一层引发相同的事件(如果您单击扩展器,焦点将不会停留在 PART_EditableTextBox 内)。
简而言之,如果您要按 TAB 键,WPF 默认情况下知道将聚焦的最终元素是组合框内的文本框,这就是组合框本身不需要它来引发事件的原因。另一方面,如果您单击组合框,WPF 需要检查哪个元素最后将获得焦点,以及是否有一些操作必须在切换焦点之前完成。
关于Focusable 属性 最后,这个对于一个控件来说,表示该控件是否可以接收到焦点,也就是用户点击该控件后,该控件可以接收键盘输入。对于设计用于接受用户输入的控件,Focusable 通常设置为 true。可以接收键盘焦点的部分是文本框。因此,如果您在组合框内设置 Focusable = false,KeyboardNavigation class 会将焦点放在组合框上,而不是文本框上,因为它无法应用其默认行为