2013-10-10 3 views
5

В программе WPF я хочу получить текущую (клавиатуру) Focus, сохранить ее и повторно установить позже.Получить и восстановить фокус на клавиатуре 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); 
    })); 
} 

Это работает один раз. Но если я попробую еще раз, это не сработает, пока я не заново создаю диалоговое окно, на которое я пытаюсь настроить фокус, даже если он делает то же самое (я проследил получение и настройку Focus). Вместо этого основное окно само по себе фокусируется.

Я когда-то слышал, что в WPF есть два вида фокуса: мне нужно установить что-то еще, чтобы получить согласованные результаты?

ответ

18

Вы верны. WPF имеет логический фокус, который вы используете там, и фокус клавиатуры. Вы можете найти полную информацию о них на странице Focus Overview MSDN. С этой страницы:

клавиатуры Фокус

клавиатуры фокус относится к элементу, который в настоящее время получает ввод с клавиатуры. На рабочем столе может быть только один элемент с фокусом клавиатуры. В WPF элемент, который имеет фокус клавиатуры, будет иметь значение IsKeyboardFocused равным true. Статическое свойство FocusedElement в классе Keyboard получает элемент, который в настоящее время имеет фокус клавиатуры.

Для того чтобы элемент мог получить фокус клавиатуры, свойства Focusable и IsVisible на базовых элементах должны быть установлены в true. Некоторые классы, такие как базовый класс Panel, по умолчанию устанавливают значение Focusable равным false; поэтому вы должны установить Focusable в true, если вы хотите, чтобы такой элемент мог получать фокус клавиатуры.

Фокус клавиатуры можно получить посредством взаимодействия пользователя с пользовательским интерфейсом, например, с помощью табуляции на элемент или нажатия мыши на определенные элементы. Фокус клавиатуры также можно получить программным путем, используя метод Focus в классе Keyboard. Метод Фокус пытается указать заданный фокус клавиатуры элемента. Возвращаемый элемент - это элемент, который имеет фокус клавиатуры, который может быть другим элементом, чем требуется, если старый или новый объект фокуса блокирует запрос.

логический фокус

Логический фокус относится к FocusManager.FocusedElement в фокусной области. Область фокусировки - это элемент, который отслеживает FocusedElement в пределах своей области. Когда фокус фокусировки покидает фокус, сфокусированный элемент потеряет фокус клавиатуры, но сохранит логический фокус. Когда фокус клавиатуры возвращается в область фокусировки, сфокусированный элемент получит фокус клавиатуры. Это позволяет изменять фокус клавиатуры между несколькими областями фокусировки, но гарантирует, что фокусированный элемент в области фокусировки восстанавливает фокус клавиатуры, когда фокус возвращается в область фокусировки.

В приложении может быть несколько элементов с логической фокусировкой, но может быть только один элемент, который имеет логический фокус в определенной области фокусировки.

Элемент с фокусом клавиатуры имеет логический фокус для области фокусировки, к которой он принадлежит.


Возвращаясь к вашему вопросу, то другой вид внимания, что вы не используете Keyboard.Focus. Вы можете использовать его как это:

Keyboard.Focus(theButtonThatYouWantToFocus); 

Кроме того, обратите внимание, что метод UIElement.Focus() будет пытаться установить как логический и фокус клавиатуры на элемент, что он был вызван. Он вернет true, если фокус клавиатуры и логический фокус были установлены на этот элемент и false, если только этот логический фокус был установлен на этот элемент.


Еще один метод, который можно использовать, чтобы сосредоточиться управления является использование 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> 

Поэтому, когда я установил IsFocused свойство истинно от модели представления, любой элемент с этим Style прикладной получит фокус. Теперь ясно, что этот Style предназначен для управления TextBox, но он по-прежнему будет работать, если вы измените его на 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, по умолчанию установлено значение Фокусность равным false. *. Это было для меня ключом. – dotNET

0

Во-первых, вы должны использовать Keyboard.Clear() и написать Keyboard.Focus("Your Input element") позже.

Keyboard.Clear() очистить свой фокус. После этого вы можете сфокусироваться на любом элементе вашего интерфейса.

Смежные вопросы