2013-10-10 13 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には2種類のフォーカスがあると聞いていましたが、一貫した結果を得るために何か他のものも設定する必要がありますか?

答えて

18

あなたは正しいです。 WPFには論理的な焦点があり、そこではキーボードフォーカスが使用されています。この2つの詳細は、MSDNのFocus Overviewページをご覧ください。そのページから:

キーボード・フォーカス

キーボード・フォーカスは、現在キーボード入力を受け取っている要素を指します。デスクトップ全体に、キーボードフォーカスを持つ要素は1つだけです。 WPFでは、キーボードフォーカスを持つ要素のIsKeyboardFocusedがtrueに設定されます。 KeyboardクラスのstaticプロパティFocusedElementは、現在キーボードフォーカスが設定されている要素を取得します。

要素でキーボードフォーカスを取得するには、基本要素のFocusableプロパティとIsVisibleプロパティをtrueに設定する必要があります。 Panel基本クラスなどの一部のクラスでは、デフォルトでFocusableがfalseに設定されています。このような要素でキーボードフォーカスを取得できるようにするには、Focusableをtrueに設定する必要があります。

キーボードのフォーカスは、要素へのタブ移動や特定の要素上でのマウスクリックなど、UIとのユーザーのやりとりを通じて取得できます。キーボードフォーカスは、KeyboardクラスのFocusメソッドを使用してプログラムで取得することもできます。 Focusメソッドは、指定された要素のキーボードフォーカスを取得しようとします。返される要素は、キーボードフォーカスを持つ要素です。これは、古いフォーカスオブジェクトまたは新しいフォーカスオブジェクトのいずれかが要求をブロックした場合に要求された要素とは異なる要素です。

論理フォーカス

論理フォーカスは、フォーカス範囲にFocusManager.FocusedElementを指します。フォーカススコープは、そのスコープ内のFocusedElementを追跡する要素です。キーボードフォーカスがフォーカススコープを離れると、フォーカスされた要素はキーボードフォーカスを失いますが、論理フォーカスを保持します。キーボードフォーカスがフォーカススコープに戻ると、フォーカスされた要素はキーボードフォーカスを取得します。これにより、複数のフォーカススコープ間でキーボードフォーカスを変更できますが、フォーカススコープにフォーカスが戻ったときに、フォーカススコープ内のフォーカスされた要素がキーボードフォーカスを確実に取得します。

アプリケーションに論理的なフォーカスを持つ複数の要素が存在する可能性がありますが、特定のフォーカススコープに論理的なフォーカスがある要素は1つのみです。

キーボードフォーカスを持つ要素には、そのフォーカススコープが論理的にフォーカスされています。


あなたの質問に戻って来て、あなたが使用していない焦点の他の種類はKeyboard.Focusです。 UIElement.Focus()方法は、それがコールされたことを要素に両方論理キーボードフォーカスを設定しようとすることに注意し、また

Keyboard.Focus(theButtonThatYouWantToFocus); 

:あなたはこのようにそれを使用することができます。論理フォーカスがこの要素に設定されている場合、キーボードフォーカスと論理フォーカスがこの要素に設定されている場合、trueを返します。およびfalseあなたがコントロールを集中するために使用することができます


もう一つの方法は、FocusManager.FocusedElementAttached Propertyを使用することです。ほとんどの人は、静的にこれを使用し、この場合には、これはただの一度時にビューのロード動作します:

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

しかし、それDataTriggerでこれを使用すると、カスタムbool財産に依存し、それを設定することが可能ですこの例では、IsFocusedプロパティ:私は、ビューモデルからtrueに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を持つ任意の要素が論理フォーカスを取得します。今度は明らかに、このStyleTextBoxのコントロールですが、たとえばControlに変更しても機能します。

+0

素晴らしい!論理フォーカスを設定するときにKeyboard.Focus(setFocus)を追加しました。これで動作します。ありがとうございました! – Sam

+0

[FocusManager.IsFocusScope](http://msdn.microsoft.com/en-us/library/system.windows.input.focusmanager.isfocusscope)を使用すると、キャプチャ/復元コードを完全に削除することができます。 aspx)。 – Olly

+0

* Panelベースクラスなどの一部のクラスでは、デフォルトでFocusableがfalseに設定されています。これが私の鍵でした。 – dotNET

0

まず、Keyboard.Clear()を使用し、後でKeyboard.Focus("Your Input element")と記述してください。

Keyboard.Clear()フォーカス参照をクリアします。その後、インターフェースのどの要素にもフォーカスを当てることができます。

関連する問題