События клавиатуры

События клавиатуры и фокус

Следующие события клавиатуры могут возникать как для аппаратных, так и сенсорных клавиатур.

Мероприятие Description
KeyDown Вызывается при нажатии клавиши.
KeyUp Вызывается при отпускании клавиши.

Внимание

Некоторые элементы управления XAML обрабатывают события ввода внутри системы. В этих случаях может показаться, что входное событие не происходит, так как прослушиватель событий не вызывает связанный обработчик. Как правило, этот подмножество ключей обрабатывается обработчиком классов, чтобы обеспечить встроенную поддержку базовой специальных возможностей клавиатуры. Например, класс Button переопределяет события OnKeyDown для ключа Пробела и клавиши ВВОД (а также OnPointerPressed) и направляет их в событие Click элемента управления. Когда нажатие клавиши обрабатывается классом элемента управления, события KeyDown и KeyUp не вызываются.
Это обеспечивает встроенный эквивалент клавиатуры для вызова кнопки, аналогично нажатию кнопки пальцем или щелчком мыши. Ключи, отличные от пробела или ввод, по-прежнему запускают события KeyDown и KeyUp. Дополнительные сведения о том, как работает обработка событий на основе классов (в частности, в разделе "Обработчики событий ввода в элементах управления"), см. в разделе "События и перенаправленные события".

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

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

Для получения фокуса ввода элемент управления должен быть включен, видим и иметь значения свойств IsTabStop и HitTestVisible true. Это состояние по умолчанию для большинства элементов управления. Если элемент управления имеет фокус ввода, он может вызывать и реагировать на события ввода клавиатуры, как описано далее в этом разделе. Вы также можете реагировать на элемент управления, получающий или теряющий фокус, обрабатывая события GotFocus и LostFocus.

По умолчанию последовательность вкладок элементов управления — это порядок, в котором они отображаются на языке разметки расширяемых приложений (XAML). Однако этот порядок можно изменить с помощью свойства TabIndex. Дополнительные сведения см. в разделе "Реализация специальных возможностей клавиатуры".

Обработчики событий клавиатуры

Обработчик событий ввода реализует делегат, предоставляющий следующие сведения:

  • Отправитель события. Отправитель сообщает объекту, в котором подключен обработчик событий.
  • Данные события. Для событий клавиатуры эти данные будут экземпляром KeyRoutedEventArgs. Делегат для обработчиков — KeyEventHandler. Наиболее релевантными свойствами KeyRoutedEventArgs для большинства сценариев обработчика являются Ключ и, возможно, KeyStatus.
  • OriginalSource. Так как события клавиатуры маршрутивируются, данные события предоставляют OriginalSource. Если вы намеренно разрешаете событиям пузыриться через дерево объектов, OriginalSource иногда является объектом озабоченности, а не отправителем. Однако это зависит от вашего дизайна. Дополнительные сведения о том , как использовать OriginalSource , а не отправитель, см. в разделе "Перенаправленные события клавиатуры" этого раздела или "События" и обзор перенаправленных событий.

Присоединение обработчика событий клавиатуры

Вы можете подключить функции обработчика событий клавиатуры для любого объекта, включающего событие в качестве члена. Это включает любой производный класс UIElement . В следующем примере XAML показано, как подключить обработчики для события KeyUp для Сетки.

<Grid KeyUp="Grid_KeyUp">
  ...
</Grid>

Вы также можете подключить обработчик событий в коде. Дополнительные сведения см. в разделе Общие сведения о событиях и перенаправленных событиях.

Определение обработчика событий клавиатуры

В следующем примере показано неполное определение обработчика событий KeyUp, присоединенного в предыдущем примере.

void Grid_KeyUp(object sender, KeyRoutedEventArgs e)
{
    //handling code here
}
Private Sub Grid_KeyUp(ByVal sender As Object, ByVal e As KeyRoutedEventArgs)
    ' handling code here
End Sub
void MyProject::MainPage::Grid_KeyUp(
  Platform::Object^ sender,
  Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
  {
      //handling code here
  }

Использование KeyRoutedEventArgs

Все события клавиатуры используют KeyRoutedEventArgs для данных событий, а KeyRoutedEventArgs содержит следующие свойства:

Виртуальные ключи

Событие KeyDown возникает при нажатии клавиши. Аналогичным образом ключ вызывается, если ключ выпущен. Обычно вы прослушиваете события для обработки определенного значения ключа. Чтобы определить, какой ключ нажимается или освобождается, проверьте значение ключа в данных события. Ключ возвращает значение VirtualKey. Перечисление VirtualKey включает все поддерживаемые ключи.

Клавиши-модификаторы

Клавиши-модификаторы — это такие клавиши, как CTRL или SHIFT, которые пользователи обычно нажимают в сочетании с другими ключами. Приложение может использовать эти сочетания в качестве пользовательских сочетаний клавиш для вызова команд приложения.

Примечание.

Встроенные сочетания клавиш см. в разделе "Ключи доступа" и акселераторы клавиатуры.

Сочетания клавиш можно обнаружить в обработчиках событий KeyDown и KeyUp. При возникновении события клавиатуры для клавиши без модификатора можно проверить, находится ли модификатор в состоянии нажатия.

Кроме того, функция GetKeyState() CoreWindow (полученная через CoreWindow.GetForCurrentThread()) также может использоваться для проверки состояния модификатора при нажатии клавиши без модификатора.

В следующих примерах реализован этот второй метод, а также код заглушки для первой реализации.

Примечание.

Клавиша ALT представлена значением VirtualKey.Menu .

Пример сочетаний клавиш

В следующем примере показано, как реализовать набор пользовательских сочетаний клавиш. В этом примере пользователи могут управлять воспроизведением мультимедиа с помощью кнопок воспроизведения, приостановки и остановки или клавиш CTRL+P, CTRL+A и сочетаний клавиш CTRL+S. В XAML кнопки отображаются сочетания клавиш с помощью подсказок и свойств AutomationProperties в метках кнопки. Эта самостоятельная документация важна для повышения удобства использования и специальных возможностей приложения. Дополнительные сведения см. в разделе "Специальные возможности клавиатуры".

Обратите внимание также, что при загрузке страница задает фокус ввода для себя. Без этого шага элемент управления не имеет начального фокуса ввода, и приложение не вызывает входные события до тех пор, пока пользователь не задает фокус ввода вручную (например, путем вкладки или щелчка элемента управления).

<Grid KeyDown="Grid_KeyDown">

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

  <MediaElement x:Name="DemoMovie" Source="xbox.wmv"
    Width="500" Height="500" Margin="20" HorizontalAlignment="Center" />

  <StackPanel Grid.Row="1" Margin="10"
    Orientation="Horizontal" HorizontalAlignment="Center">

    <Button x:Name="PlayButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+P"
      AutomationProperties.AcceleratorKey="Control P">
      <TextBlock>Play</TextBlock>
    </Button>

    <Button x:Name="PauseButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+A"
      AutomationProperties.AcceleratorKey="Control A">
      <TextBlock>Pause</TextBlock>
    </Button>

    <Button x:Name="StopButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+S"
      AutomationProperties.AcceleratorKey="Control S">
      <TextBlock>Stop</TextBlock>
    </Button>

  </StackPanel>

</Grid>
//showing implementations but not header definitions
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
    (void) e;    // Unused parameter
    this->Loaded+=ref new RoutedEventHandler(this,&amp;MainPage::ProgrammaticFocus);
}
void MainPage::ProgrammaticFocus(Object^ sender, RoutedEventArgs^ e) 
{
    this->Focus(Windows::UI::Xaml::FocusState::Programmatic);
}

void KeyboardSupport::MainPage::MediaButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
    FrameworkElement^ fe = safe_cast<FrameworkElement^>(sender);
    if (fe->Name == "PlayButton") {DemoMovie->Play();}
    if (fe->Name == "PauseButton") {DemoMovie->Pause();}
    if (fe->Name == "StopButton") {DemoMovie->Stop();}
}


bool KeyboardSupport::MainPage::IsCtrlKeyPressed()
{
    auto ctrlState = CoreWindow::GetForCurrentThread()->GetKeyState(VirtualKey::Control);
    return (ctrlState & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down;
}

void KeyboardSupport::MainPage::Grid_KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
{
    if (e->Key == VirtualKey::Control) isCtrlKeyPressed = true;
}


void KeyboardSupport::MainPage::Grid_KeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
{
    if (IsCtrlKeyPressed()) 
    {
        if (e->Key==VirtualKey::P) { DemoMovie->Play(); }
        if (e->Key==VirtualKey::A) { DemoMovie->Pause(); }
        if (e->Key==VirtualKey::S) { DemoMovie->Stop(); }
    }
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    // Set the input focus to ensure that keyboard events are raised.
    this.Loaded += delegate { this.Focus(FocusState.Programmatic); };
}

private void MediaButton_Click(object sender, RoutedEventArgs e)
{
    switch ((sender as Button).Name)
    {
        case "PlayButton": DemoMovie.Play(); break;
        case "PauseButton": DemoMovie.Pause(); break;
        case "StopButton": DemoMovie.Stop(); break;
    }
}

private static bool IsCtrlKeyPressed()
{
    var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
    return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
}

private void Grid_KeyDown(object sender, KeyRoutedEventArgs e)
{
    if (IsCtrlKeyPressed())
    {
        switch (e.Key)
        {
            case VirtualKey.P: DemoMovie.Play(); break;
            case VirtualKey.A: DemoMovie.Pause(); break;
            case VirtualKey.S: DemoMovie.Stop(); break;
        }
    }
}
Private isCtrlKeyPressed As Boolean
Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)

End Sub

Private Function IsCtrlKeyPressed As Boolean
    Dim ctrlState As CoreVirtualKeyStates = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
    Return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
End Function

Private Sub Grid_KeyDown(sender As Object, e As KeyRoutedEventArgs)
    If IsCtrlKeyPressed() Then
        Select Case e.Key
            Case Windows.System.VirtualKey.P
                DemoMovie.Play()
            Case Windows.System.VirtualKey.A
                DemoMovie.Pause()
            Case Windows.System.VirtualKey.S
                DemoMovie.Stop()
        End Select
    End If
End Sub

Private Sub MediaButton_Click(sender As Object, e As RoutedEventArgs)
    Dim fe As FrameworkElement = CType(sender, FrameworkElement)
    Select Case fe.Name
        Case "PlayButton"
            DemoMovie.Play()
        Case "PauseButton"
            DemoMovie.Pause()
        Case "StopButton"
            DemoMovie.Stop()
    End Select
End Sub

Примечание.

Параметр AutomationProperties.AcceleratorKey или AutomationProperties.AccessKey в XAML предоставляет строковые сведения, которые документируют сочетания клавиш для вызова конкретного действия. Данные записываются клиентами Microsoft модель автоматизации пользовательского интерфейса, такими как экранный диктор, и обычно предоставляются пользователю напрямую.

Настройка AutomationProperties.AcceleratorKey или AutomationProperties.AccessKey не имеет никаких действий самостоятельно. Для фактического реализации сочетания клавиш в приложении необходимо подключить обработчики событий KeyDown или KeyUp. Кроме того, оформление текста подчеркивания для ключа доступа не предоставляется автоматически. Необходимо явно подчеркнуть текст для определенного ключа в mnemonic, как встроенное форматирование подчеркивания , если вы хотите отобразить подчеркнутый текст в пользовательском интерфейсе.

 

Перенаправленные события клавиатуры

Некоторые события перенаправляются, включая KeyDown и KeyUp. Перенаправленные события используют стратегию маршрутизации пузырьков. Стратегия маршрутизации пузырьков означает, что событие происходит из дочернего объекта и затем направляется к последовательным родительским объектам в дереве объектов. Это дает еще одну возможность обрабатывать то же событие и взаимодействовать с теми же данными событий.

Рассмотрим следующий пример XAML, который обрабатывает события KeyUp для холста и двух объектов Button. В этом случае, если вы выпустили ключ во время фокуса, удерживаемого объектом Button , оно вызывает событие KeyUp . Затем событие пузырится до родительского холста.

<StackPanel KeyUp="StackPanel_KeyUp">
  <Button Name="ButtonA" Content="Button A"/>
  <Button Name="ButtonB" Content="Button B"/>
  <TextBlock Name="statusTextBlock"/>
</StackPanel>

В следующем примере показано, как реализовать обработчик событий KeyUp для соответствующего содержимого XAML в предыдущем примере.

void StackPanel_KeyUp(object sender, KeyRoutedEventArgs e)
{
    statusTextBlock.Text = String.Format(
        "The key {0} was pressed while focus was on {1}",
        e.Key.ToString(), (e.OriginalSource as FrameworkElement).Name);
}

Обратите внимание на использование свойства OriginalSource в предыдущем обработчике. Здесь OriginalSource сообщает объект, вызвавшее событие. Объект не может быть StackPanel, так как StackPanel не является элементом управления и не может иметь фокус. Только одна из двух кнопок в StackPanel , возможно, вызвала событие, но какой из них? Используйте OriginalSource для различения фактического исходного объекта события, если вы обрабатываете событие родительского объекта.

Свойство Handled в данных события

В зависимости от стратегии обработки событий может потребоваться, чтобы только один обработчик событий реагировал на событие пузырьков. Например, если у вас есть определенный обработчик KeyUp , подключенный к одному из элементов управления Button , он будет иметь первую возможность обрабатывать это событие. В этом случае может потребоваться, чтобы родительская панель также обрабатывала событие. Для этого сценария можно использовать свойство Handled в данных события.

Цель свойства Handled в классе данных перенаправленного события — сообщить о том, что еще один обработчик, зарегистрированный ранее в маршруте событий, уже действовал. Это влияет на поведение перенаправленной системы событий. Если в обработчике событий задано значение True, это событие останавливает маршрутизацию и не отправляется в последовательные родительские элементы.

События клавиатуры AddHandler и уже обработаны

Вы можете использовать специальный метод для присоединения обработчиков, которые могут действовать над событиями, которые уже помечены как обработанные. Этот метод использует метод AddHandler для регистрации обработчика, а не использования атрибутов XAML или синтаксиса для добавления обработчиков, таких как += в C#.

Общее ограничение этого метода заключается в том, что API AddHandler принимает параметр типа RoutedEvent, определяющий перенаправленное событие в вопросе. Не все перенаправленные события предоставляют идентификатор RoutedEvent , и это внимание, таким образом, влияет на то, какие перенаправленные события по-прежнему можно обрабатывать в обработанном случае. События KeyDown и KeyUp имеют перенаправленные идентификаторы событий (KeyDownEvent и KeyUpEvent) в UIElement. Однако другие события, такие как TextBox.TextChanged , не имеют перенаправленных идентификаторов событий и поэтому не могут использоваться с методом AddHandler .

Переопределение событий клавиатуры и поведения

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

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

  public class CustomGridView : GridView
  {
    protected override void OnKeyDown(KeyRoutedEventArgs e)
    {
      // Override arrow key behaviors.
      if (e.Key != Windows.System.VirtualKey.Left && e.Key !=
        Windows.System.VirtualKey.Right && e.Key !=
          Windows.System.VirtualKey.Down && e.Key !=
            Windows.System.VirtualKey.Up)
              base.OnKeyDown(e);
      else
        FocusManager.TryMoveFocus(FocusNavigationDirection.Down);
    }
  }

Примечание.

При использовании GridView только для макета рекомендуется использовать другие элементы управления, такие как ItemsControl с ItemsWrapGrid.

Система команд

Небольшое количество элементов пользовательского интерфейса обеспечивает встроенную поддержку команд. Команда использует перенаправленные события, связанные с входными данными, в базовой реализации. Он позволяет обрабатывать связанные входные данные пользовательского интерфейса, такие как определенное действие указателя или определенный ключ акселератора, вызывая один обработчик команд.

Если команда доступна для элемента пользовательского интерфейса, рассмотрите возможность использования интерфейсов API команд вместо каких-либо дискретных событий ввода. Дополнительные сведения см. в разделе ButtonBase.Command.

Вы также можете реализовать ICommand для инкапсулировать функции команд, которые вызываются из обычных обработчиков событий. Это позволяет использовать команду, даже если не доступно свойство Command .

Ввод текста и элементы управления

Некоторые элементы управления реагируют на события клавиатуры с собственной обработкой. Например, TextBox — это элемент управления, предназначенный для записи, а затем визуально представлять текст, введенный с помощью клавиатуры. Он использует KeyUp и KeyDown в собственной логике для записи нажатий клавиш, а также вызывает собственное событие TextChanged , если текст фактически изменился.

Вы по-прежнему можете добавлять обработчики для KeyUp и KeyDown в текстовое поле или любой связанный элемент управления, предназначенный для обработки ввода текста. Однако в рамках своей предполагаемой структуры элемент управления может не реагировать на все ключевые значения, направленные на него с помощью ключевых событий. Поведение зависит от каждого элемента управления.

Например, ButtonBase (базовый класс для button) обрабатывает keyUp, чтобы он смог проверить пробел или клавишу ВВОД. ButtonBase считает keyUp эквивалентным левой кнопке мыши для создания события Click . Эта обработка события выполняется, когда ButtonBase переопределяет виртуальный метод OnKeyUp. В реализации он задает значение True. Результатом является то, что любой родительский элемент кнопки, прослушивающий ключевое событие, в случае пробела, не получит уже обработанное событие для своих собственных обработчиков.

Другим примером является TextBox. Некоторые ключи, такие как клавиши со стрелками, не считаются текстом TextBox и вместо этого считаются конкретными для поведения пользовательского интерфейса элемента управления. Текстовое поле помечает эти случаи событий как обрабатываемые.

Пользовательские элементы управления могут реализовать собственное поведение переопределения для ключевых событий, переопределив OnKeyDown / OnKeyUp. Если пользовательский элемент управления обрабатывает определенные клавиши акселератора или имеет поведение элемента управления или фокуса, аналогичное сценарию, описанному в TextBox, следует поместить эту логику в собственные переопределения OnKeyDown / OnKeyUp.

Сенсорная клавиатура

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

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

Если вы создаете пользовательский элемент управления, требующий ввода текста, но не производный от стандартного элемента управления вводом текста, можно добавить поддержку сенсорной клавиатуры, реализуя правильные шаблоны элементов управления модель автоматизации пользовательского интерфейса. Дополнительные сведения см. в примере клавиатуры Touch.

Нажатие клавиш на сенсорной клавиатуре вызывает события KeyDown и KeyUp так же, как нажатие клавиши на аппаратных клавиатурах. Однако сенсорный клавиатура не будет вызывать входные события для клавиш CTRL+A, CTRL+Z, CTRL+X, CTRL+C и CTRL+V, которые зарезервированы для обработки текста в элементе управления входными данными.

Пользователи смогут вводить данные в вашем приложении гораздо быстрее и с меньшими усилиями, если вы настроите тип вводимых данных элемента управления текстом в соответствии с типом вводимых данных. Область ввода предоставляет указание типа ввода текста, ожидаемого элементом управления, чтобы система может предоставить специализированный сенсорный раскладку клавиатуры для типа ввода. Например, если текстовое поле используется только для ввода 4-значного PIN-кода, установите для свойства InputScope значение Number. Это позволяет системе отображать цифровой макет клавиатуры, что упрощает ввод ПИН-кода пользователем. Дополнительные сведения см. в разделе "Использование области ввода" для изменения сенсорной клавиатуры.

Разработчикам

Конструкторы

Примеры

Архивные примеры