Поделиться через


Общие сведения о фокусе

Обновлен: Ноябрь 2007

Приложение WPF содержит две главные концепции, связанные с фокусом: фокус ввода и логический фокус. Фокус ввода ссылается на элемент, который получает ввод данных с клавиатуры, а логической фокус ссылается на элемент в области, на которой установлен фокус. Эти понятия подробно обсуждаются в этом разделе. Общее представление о различии в этих понятиях важно для создания сложных приложений, имеющих несколько областей, в которых можно получить фокус.

Основными классами, которые участвуют в управлении фокусом, является класс Keyboard, класс FocusManager и классы базовых элементов, такие как UIElement и ContentElement. Дополнительные сведения о базовых элементах содержатся в разделе Общие сведения о базовых элементах.

Класс Keyboard относится, в основном, к фокусу ввода, а класс FocusManager — к логическому фокусу, но это не абсолютное различие. Элемент, имеющий фокус ввода, также будет иметь логический фокус, но элемент, имеющий логический фокус, не обязательно имеет фокус ввода. Это видно при использовании класса Keyboard для задания элемента, имеющего фокус ввода, потому что он также задает логический фокус на этом элементе.

В этом разделе содержатся следующие подразделы.

  • Фокус ввода
  • Логический фокус
  • Навигация с помощью клавиатуры
  • Перемещение фокуса программными средствами
  • События фокуса
  • Связанные разделы

Фокус ввода

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

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

Фокус ввода может быть получен с помощью взаимодействия пользователя с Пользовательский интерфейс, например — перехода к элементу или щелчка мышью определенных элементов. Фокус клавиатуры также может быть получен программными средствами с помощью метода 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 для классов базовых элементов получает значение, указывающее, имеет ли элемент, или один из его видимых дочерних элементов, фокус ввода.

Когда устанавливается начальный фокус при запуске приложения, элемент, получающий фокус, должен быть подключен к объекту PresentationSource, и для его свойства Focusable и IsVisible должно быть установлено значение true. Рекомендуемым местом для установки начального фокуса является обработчик событий Loaded. Обратный вызов Dispatcher может также использоваться посредством вызова метода Invoke или BeginInvoke.

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

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

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

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

Элемент может быть включен в область фокуса в Язык XAML (Extensible Application Markup Language) путем установки для вложенного свойства IsFocusScope объекта FocusManager значения 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, стрелка вверх, стрелка вниз, левая стрелка и правая стрелка.

Поведение перехода контейнера перехода можно изменить при помощи вложенных свойств KeyboardNavigationTabNavigationControlTabNavigation и DirectionalNavigation. Эти свойства являются объектом KeyboardNavigationMode типа, и возможными значениями являются: Continue, Local, Contained, Cycle, Once и None. Значение по умолчанию — Continue, которое означает, что элемент не является контейнером навигации.

В следующем примере создается объект Menu с объектами MenuItem. Для вложенного свойства TabNavigation в объекте Menu устанавливается значение Cycle. При изменении фокуса с помощью клавиши 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, DownLeft и 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.

См. также

Основные понятия

Общие сведения о входных данных

Общие сведения о базовых элементах

Ссылки

FocusManager

UIElement

ContentElement