Общие сведения о фокусе
Существует два основных понятия, относящихся к фокусу в WPF: фокус клавиатуры и логический фокус. Фокус клавиатуры ссылается на элемент, получающий ввод с клавиатуры, а логический фокус ссылается на элемент в области фокуса, имеющий фокус. Эти понятия подробно освещаются в этом обзоре. Важно понимать разницу между этими понятиями, чтобы создавать сложные приложения с несколькими областями, в которых можно получить фокус.
Основные классы, участвующие в управлении фокусом являются Keyboard класс, FocusManager класс и базовых элементов классы, такие как UIElement и ContentElement. Дополнительные сведения о базовых элементах см. в разделе Общие сведения о базовых элементах.
Keyboard Класс занимается в основном с фокусом клавиатуры и FocusManager занимается в основном с логическим фокусом, однако это не является абсолютным. Элемент, имеющий фокус клавиатуры, также будет иметь логический фокус, но элемент, имеющий логический фокус, не обязательно будет иметь фокус клавиатуры. Это видно при использовании Keyboard классу задать элемент, имеющий фокус клавиатуры, он также устанавливает логический фокус на элемент.
Фокус клавиатуры
Фокус клавиатуры относится к элементу, получающему ввод с клавиатуры. На всем рабочем столе может быть только один элемент, в котором находится фокус клавиатуры. В WPF, будет иметь элемент, имеющий фокус клавиатуры IsKeyboardFocused присвоено true
. Статическое свойство FocusedElement на Keyboard класс получает элемент, который в данный момент имеет фокус клавиатуры.
Чтобы элемент мог получить фокус клавиатуры Focusable и IsVisible свойства базовых элементов должно быть присвоено true
. Некоторые классы, такие как Panel базового класса, имеют Focusable присвоено false
по умолчанию; таким образом, необходимо задать Focusable для true
Если требуется, чтобы элемент мог получить фокус клавиатуры.
Фокус клавиатуры можно получить с помощью взаимодействия пользователя с UI, например перехода к элементу или щелчка мышью определенных элементов. Фокус клавиатуры также могут быть получены программно с помощью Focus метод Keyboard класса. Focus Метод пытается передать фокус клавиатуры для указанного элемента. Возвращаемый элемент — это элемент, имеющий фокус клавиатуры, который может отличаться от запрошенного, если старый или новый объект фокуса блокирует запрос.
В следующем примере используется Focus метод, чтобы установить фокус на Button.
private void OnLoaded(object sender, RoutedEventArgs e)
{
// Sets keyboard focus on the first Button in the sample.
Keyboard.Focus(firstButton);
}
IsKeyboardFocused Свойство в классах базовых элементов получает значение, указывающее, имеет ли элемент фокус клавиатуры. IsKeyboardFocusWithin Свойство в классах базовых элементов получает значение, указывающее, имеет ли элемент или один из его визуальных дочерних элементов фокус клавиатуры.
При настройке начального фокуса при запуске приложения, элемент должен получить фокус должен быть в визуальном дереве первоначального окна, загружаемого этим приложением, и элемент должен иметь Focusable и IsVisible присвоено true
. Рекомендуется устанавливать исходный фокус начинается в Loaded обработчик событий. Объект Dispatcher обратного вызова также можно путем вызова Invoke или BeginInvoke.
Логический фокус
Логический фокус относится к FocusManager.FocusedElement в области фокуса. Область фокуса — элемент, который отслеживает FocusedElement внутри своей области. Когда фокус клавиатуры покидает область фокуса, элемент с фокусом теряет фокус клавиатуры, но сохраняет логический фокус. При возвращении фокуса клавиатуры в область фокуса элемент с логическим фокусом получит фокус клавиатуры. Это позволяет переносить фокус клавиатуры между несколькими областями фокуса, но гарантирует, что элемент с фокусом в области фокуса останется элементом с фокусом клавиатуры, когда фокус вернется в эту область.
В приложении может быть несколько элементов, имеющих логический фокус, но в отдельной области фокуса может быть только один элемент, имеющий логический фокус.
Элемент, имеющий фокус клавиатуры, имеет логический фокус для области фокуса, которой он принадлежит.
Элемент может быть включен в область фокуса в XAML , задав FocusManager присоединенное свойство IsFocusScope для true
. В коде, элемент может быть включен в область фокуса путем вызова SetIsFocusScope.
В нижеследующем примере StackPanel в область фокуса, задав IsFocusScope вложенного свойства зависимостей.
<StackPanel Name="focusScope1"
FocusManager.IsFocusScope="True"
Height="200" Width="200">
<Button Name="button1" Height="50" Width="50"/>
<Button Name="button2" Height="50" Width="50"/>
</StackPanel>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
GetFocusScope Возвращает область фокуса для заданного элемента.
Классы в WPF являются областями фокуса по умолчанию Window, MenuItem, ToolBar, и ContextMenu.
GetFocusedElement Получает элемент с фокусом для заданной области фокуса. SetFocusedElement Задает элемент с фокусом в заданной области фокуса. SetFocusedElement обычно используется для задания исходного элемента с фокусом.
В следующем примере элемент с фокусом задается в области фокуса и возвращает элемент с фокусом для области фокуса.
// Sets the focused element in focusScope1
// focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2);
// Gets the focused element for focusScope 1
IInputElement focusedElement = FocusManager.GetFocusedElement(focusScope1);
Навигация с помощью клавиатуры
KeyboardNavigation Класс отвечает за реализацию навигации с фокусом клавиатуры по умолчанию, когда нажата одна из клавиш навигации. Клавиши навигации: Клавиши TAB, SHIFT + TAB, CTRL + TAB, CTRL + SHIFT + TAB, Стрелка вверх, Стрелка вниз, Стрелка влево и Стрелка вправо.
Поведение навигации контейнера навигации можно изменить при помощи вложенных KeyboardNavigation свойства TabNavigation, ControlTabNavigation, и DirectionalNavigation. Эти свойства имеют тип KeyboardNavigationMode и возможные значения: Continue, Local, Contained, Cycle, Once, и None. Значение по умолчанию — Continue, который означает, что элемент не является контейнером навигации.
В следующем примере создается Menu с количеством MenuItem объектов. TabNavigation Присоединенное свойство имеет значение Cycle на Menu. При изменении фокуса с помощью клавиши tab в Menu, фокус перемещается из каждого элемента, и при достижении последнего элемента переходит к первому элементу.
<Menu KeyboardNavigation.TabNavigation="Cycle">
<MenuItem Header="Menu Item 1" />
<MenuItem Header="Menu Item 2" />
<MenuItem Header="Menu Item 3" />
<MenuItem Header="Menu Item 4" />
</Menu>
Menu navigationMenu = new Menu();
MenuItem item1 = new MenuItem();
MenuItem item2 = new MenuItem();
MenuItem item3 = new MenuItem();
MenuItem item4 = new MenuItem();
navigationMenu.Items.Add(item1);
navigationMenu.Items.Add(item2);
navigationMenu.Items.Add(item3);
navigationMenu.Items.Add(item4);
KeyboardNavigation.SetTabNavigation(navigationMenu,
KeyboardNavigationMode.Cycle);
Перемещение фокуса программными средствами
Дополнительные API для работы с фокусом являются MoveFocus и PredictFocus.
MoveFocus изменения фокуса к следующему элементу в приложении. Объект TraversalRequest используется для указания направления. FocusNavigationDirection Передается MoveFocus указывает, можно перемещать фокус разных направлениях, таких как First, Last, Up и Down.
В следующем примере используется MoveFocus Чтобы изменить элемент с фокусом.
// Creating a FocusNavigationDirection object and setting it to a
// local field that contains the direction selected.
FocusNavigationDirection focusDirection = _focusMoveValue;
// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);
// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;
// Change keyboard focus.
if (elementWithFocus != null)
{
elementWithFocus.MoveFocus(request);
}
PredictFocus Возвращает объект, который должен получить фокус, если фокус должен быть изменен. В настоящее время только Up, Down, Left, и Right поддерживаются PredictFocus.
События фокуса
События, связанные с фокусом клавиатуры: PreviewGotKeyboardFocus, GotKeyboardFocus и PreviewLostKeyboardFocus, LostKeyboardFocus. События определяются как вложенные события в Keyboard класса, но более легко доступны как эквивалентные перенаправленные события в классах базовых элементов. Дополнительные сведения о событиях см. в разделе Общие сведения о перенаправленных событиях.
GotKeyboardFocus вызывается, когда элемент получает фокус клавиатуры. LostKeyboardFocus вызывается, когда элемент теряет фокус клавиатуры. Если PreviewGotKeyboardFocus событий или PreviewLostKeyboardFocusEvent событие обрабатывается и Handled присваивается true
, а затем фокус не изменится.
В следующем примере подключается GotKeyboardFocus и LostKeyboardFocus обработчики событий для TextBox.
<Border BorderBrush="Black" BorderThickness="1"
Width="200" Height="100" Margin="5">
<StackPanel>
<Label HorizontalAlignment="Center" Content="Type Text In This TextBox" />
<TextBox Width="175"
Height="50"
Margin="5"
TextWrapping="Wrap"
HorizontalAlignment="Center"
VerticalScrollBarVisibility="Auto"
GotKeyboardFocus="TextBoxGotKeyboardFocus"
LostKeyboardFocus="TextBoxLostKeyboardFocus"
KeyDown="SourceTextKeyDown"/>
</StackPanel>
</Border>
Когда TextBox получает фокус клавиатуры, Background свойство TextBox изменяется на LightBlue.
private void TextBoxGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
TextBox source = e.Source as TextBox;
if (source != null)
{
// Change the TextBox color when it obtains focus.
source.Background = Brushes.LightBlue;
// Clear the TextBox.
source.Clear();
}
}
Когда TextBox теряет фокус клавиатуры, Background свойство TextBox изменяется обратно на белое.
private void TextBoxLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
TextBox source = e.Source as TextBox;
if (source != null)
{
// Change the TextBox color when it loses focus.
source.Background = Brushes.White;
// Set the hit counter back to zero and updates the display.
this.ResetCounter();
}
}
События, связанные с логическим фокусом: GotFocus и LostFocus. Эти события определяются в FocusManager как Прикрепленные события, но FocusManager не предоставляет оболочки событий среды CLR. UIElement и ContentElement предоставляют эти события более удобным.