获取和恢复 WPF 键盘焦点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19289994/
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
Get and restore WPF keyboard focus
提问by Sam
In a WPF program I want to get the current (keyboard) Focus, store it and re-set it later.
在 WPF 程序中,我想获取当前(键盘)焦点,将其存储并稍后重新设置。
To get the current focus right now I use:
要立即获得当前焦点,我使用:
DependencyObject focusScope = FocusManager.GetFocusScope(d);
_lastFocus = FocusManager.GetFocusedElement(focusScope);
To set it later I use:
要稍后设置,我使用:
if (_lastFocus != null)
{
IInputElement setFocus = _lastFocus;
_lastFocus = null;
d.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new ThreadStart(delegate
{
FocusManager.SetFocusedElement(d, setFocus);
}));
}
This works once. But if I try again, it does not work until I re-create the offending dialog which I try to set the focus to, even though it does the very same thing (I traced getting and setting the Focus). Instead the main window itself gets the focus.
这工作一次。但是,如果我再试一次,它就不会工作,直到我重新创建我尝试将焦点设置到的有问题的对话框,即使它做了同样的事情(我跟踪了获取和设置焦点)。相反,主窗口本身获得焦点。
I once heard there are two kinds of focus in WPF, do I need to set something else, too, to get consistent results?
我曾经听说 WPF 中有两种焦点,我是否还需要设置其他内容以获得一致的结果?
回答by Sheridan
You are correct. WPF has logical focus, which you are using there and keyboard focus. You can find full details of the two in the Focus Overviewpage of MSDN. From that page:
你是对的。WPF 具有逻辑焦点,您在那里使用它和键盘焦点。您可以在MSDN的Focus Overview页面中找到两者的完整详细信息。从该页面:
Keyboard Focus
键盘焦点
Keyboard focus refers to the element that is currently receiving keyboard input. There can be only one element on the whole desktop that has keyboard focus. In WPF, the element that has keyboard focus will have IsKeyboardFocused set to true. The static property FocusedElement on the Keyboard class gets the element that currently has keyboard focus.
In order for an element to obtain keyboard focus, the Focusable and the IsVisible properties on the base elements must be set to true. Some classes, such as the Panel base class, have Focusable set to false by default; therefore, you must set Focusable to true if you want such an element to be able to obtain keyboard focus.
Keyboard focus can be obtained through user interaction with the UI, such as tabbing to an element or clicking the mouse on certain elements. Keyboard focus can also be obtained programmatically by using the Focus method on the Keyboard class. The Focus method attempts to give the specified element keyboard focus. The returned element is the element that has keyboard focus, which might be a different element than requested if either the old or new focus object block the request.
键盘焦点是指当前正在接收键盘输入的元素。整个桌面上只能有一个具有键盘焦点的元素。在 WPF 中,具有键盘焦点的元素会将 IsKeyboardFocused 设置为 true。Keyboard 类上的静态属性 FocusedElement 获取当前具有键盘焦点的元素。
为了让元素获得键盘焦点,基本元素的 Focusable 和 IsVisible 属性必须设置为 true。某些类,例如 Panel 基类,默认情况下将 Focusable 设置为 false;因此,如果您希望这样的元素能够获得键盘焦点,则必须将 Focusable 设置为 true。
键盘焦点可以通过用户与 UI 的交互获得,例如使用 Tab 键切换到某个元素或在某些元素上单击鼠标。也可以通过使用 Keyboard 类上的 Focus 方法以编程方式获得键盘焦点。Focus 方法尝试为指定的元素提供键盘焦点。返回的元素是具有键盘焦点的元素,如果旧的或新的焦点对象阻止请求,则该元素可能与请求的元素不同。
Logical Focus
逻辑焦点
Logical focus refers to the FocusManager.FocusedElement in a focus scope. A focus scope is an element that keeps track of the FocusedElement within its scope. When keyboard focus leaves a focus scope, the focused element will lose keyboard focus but will retain logical focus. When keyboard focus returns to the focus scope, the focused element will obtain keyboard focus. This allows for keyboard focus to be changed between multiple focus scopes but ensures that the focused element in the focus scope regains keyboard focus when focus returns to the focus scope.
There can be multiple elements that have logical focus in an application, but there may only be one element that has logical focus in a particular focus scope.
An element that has keyboard focus has logical focus for the focus scope it belongs to.
逻辑焦点是指焦点范围内的 FocusManager.FocusedElement。焦点范围是在其范围内跟踪 FocusedElement 的元素。当键盘焦点离开焦点范围时,焦点元素将失去键盘焦点但会保留逻辑焦点。当键盘焦点返回焦点范围时,焦点元素将获得键盘焦点。这允许在多个焦点范围之间更改键盘焦点,但确保焦点范围中的焦点元素在焦点返回到焦点范围时重新获得键盘焦点。
一个应用程序中可以有多个具有逻辑焦点的元素,但在特定的焦点范围内可能只有一个元素具有逻辑焦点。
具有键盘焦点的元素对其所属的焦点范围具有逻辑焦点。
Coming back to your question, the other kind of focus that you are not using is Keyboard.Focus
. You can use it like this:
回到你的问题,你没有使用的另一种焦点是Keyboard.Focus
. 你可以这样使用它:
Keyboard.Focus(theButtonThatYouWantToFocus);
Also, note that the UIElement.Focus()
method will attempt to set bothlogical andkeyboard focus to the element that it was called on. It will return true
if keyboard focus and logical focus were set to this elementand false
if only logical focus was set to this element.
另外,还要注意的是,UIElement.Focus()
方法将尝试设置两个逻辑和键盘焦点元素,它被称为上。true
如果键盘焦点和逻辑焦点被设置到这个元素,false
并且只有逻辑焦点被设置到这个元素,它将返回。
One other method that you can use to focus controls is to use the FocusManager.FocusedElement
Attached Property
. Most people use this statically and in this case, this will work just once when the view loads:
可用于聚焦控件的另一种方法是使用FocusManager.FocusedElement
Attached Property
. 大多数人静态地使用它,在这种情况下,当视图加载时,它只会工作一次:
<Grid FocusManager.FocusedElement="{Binding ElementName=TextBoxToFocus}">
<TextBox Name="TextBoxToFocus" Text="Focus Me" />
<Grid>
However, it ispossible to use this in a DataTrigger
and to set it dependent on a custom bool
property, in this example, the IsFocused
property:
但是,它是可以在使用这个DataTrigger
并设置它依赖于一个自定义bool
属性,在这个例子中,IsFocused
属性:
<Style x:Key="FocusableTextBoxStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused}" Value="True">
<Setter Property="FocusManager.FocusedElement"
Value="{Binding RelativeSource={RelativeSource Self}}" />
</DataTrigger>
</Style.Triggers>
</Style>
So whenever I set the IsFocused
property to true from the view model, any element with this Style
applied will get logical focus. Now clearly, this Style
is for the TextBox
control, but it will still work if you change it to Control
for instance.
因此,每当我将IsFocused
视图模型中的属性设置为 true 时,应用此属性的任何元素Style
都将获得逻辑焦点。现在很明显,这Style
是用于TextBox
控件的,但是如果您将其更改Control
为例如,它仍然可以工作。
回答by Alberto
First, you should use Keyboard.ClearFocus()
and write Keyboard.Focus("Your Input element")
later.
首先,您应该稍后使用Keyboard.ClearFocus()
和编写Keyboard.Focus("Your Input element")
。
Keyboard.ClearFocus()
clear your focus reference. After, you can do focus to whatever element of your interface.
Keyboard.ClearFocus()
清除您的焦点参考。之后,您可以专注于界面的任何元素。