2013-10-10 140 views
5

在WPF程序中,我想获取当前(键盘)焦点,将其存储并稍后重新设置。获取并恢复WPF键盘焦点

要获得目前的工作重点,现在我使用:

DependencyObject focusScope = FocusManager.GetFocusScope(d); 
_lastFocus = FocusManager.GetFocusedElement(focusScope); 

要设置后来我用:

if (_lastFocus != null) 
{ 
    IInputElement setFocus = _lastFocus; 
    _lastFocus = null; 
    d.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new ThreadStart(delegate 
    { 
    FocusManager.SetFocusedElement(d, setFocus); 
    })); 
} 

只能用一次。但是如果我再试一次,它将不起作用,直到我重新创建我试图设置焦点的有问题的对话框,即使它做了同样的事情(我追踪到了并设置焦点)。主窗口本身就是焦点所在。

我曾经听说WPF中有两种焦点,我是否还需要设置其他的东西来获得一致的结果?

回答

18

你是对的。 WPF具有逻辑焦点,您在那里使用和键盘焦点。您可以在MSDN的Focus Overview页面找到这两者的完整详细信息。从这个页面:

键盘焦点

键盘焦点是指当前正在接收键盘输入的元素。整个桌面上只能有一个键盘焦点的元素。在WPF中,具有键盘焦点的元素将IsKeyboardFocused设置为true。 Keyboard类上的静态属性FocusedElement获取当前具有键盘焦点的元素。

为了使元素获得键盘焦点,必须将基本元素上的Focusable和IsVisible属性设置为true。某些类(例如面板基类)的Focusable默认设置为false;因此,如果您希望这样的元素能够获得键盘焦点,则必须将Focusable设置为true。

键盘焦点可以通过用户与UI的交互获得,例如对元素进行标签或在某些元素上单击鼠标。键盘焦点也可以通过使用Keyboard类上的Focus方法以编程方式获得。 Focus方法尝试给出指定元素的键盘焦点。返回的元素是具有键盘焦点的元素,如果旧焦点对象或新焦点对象阻止该请求,则该元素可能与请求不同。

逻辑焦点

逻辑焦点指FocusManager.FocusedElement在聚焦范围。焦点范围是一个跟踪其范围内的FocusedElement的元素。当键盘焦点离开焦点范围时,焦点元素将失去键盘焦点,但会保留逻辑焦点。当键盘焦点返回焦点范围时,焦点元素将获得键盘焦点。这允许在多个焦点范围之间改变键盘焦点,但是确保当焦点返回焦点范围时,焦点范围中的焦点元素重新获得键盘焦点。

可以有多个元素在应用程序中具有逻辑焦点,但在特定焦点范围内可能只有一个元素具有逻辑焦点。

具有键盘焦点的元素对于它所属的焦点范围具有逻辑焦点。


现在回到你的问题,你是不是使用其他种类的焦点是Keyboard.Focus。您可以使用它像这样:

Keyboard.Focus(theButtonThatYouWantToFocus); 

而且,请注意UIElement.Focus()方法将尝试逻辑键盘焦点设置到元素,它被称为上。如果仅将逻辑焦点设置为此元素,如果将键盘焦点和逻辑焦点设置为此元素和false,它将返回true


,你可以用它来集中控制的另外一个方法是使用FocusManager.FocusedElementAttached Property。大多数人静态使用,在这种情况下,当视图加载这将工作只是一次:

<Grid FocusManager.FocusedElement="{Binding ElementName=TextBoxToFocus}"> 
    <TextBox Name="TextBoxToFocus" Text="Focus Me" /> 
<Grid> 

然而,可能在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> 

所以每当我从视图模型,这个Style应用将获得逻辑焦点任何元素设置IsFocused属性为true。现在很清楚,Style用于控制TextBox,但如果将其更改为Control,它仍然可以工作。

+0

太棒了!我在设置逻辑焦点时添加了Keyboard.Focus(setFocus),现在它可以工作,非常感谢! – Sam

+0

通过使用[FocusManager.IsFocusScope](http://msdn.microsoft.com/zh-cn/library/system.windows.input.focusmanager.isfocusscope),您实际上可以完全消除捕获/恢复代码。 ASPX)。 – Olly

+0

*某些类(例如Panel基类)的Focusable默认设置为false *。这是我的关键。 – dotNET

0

首先,您应该使用Keyboard.Clear(),稍后再写Keyboard.Focus("Your Input element")

Keyboard.Clear()明确您的焦点参考。之后,您可以专注于界面的任何元素。