/// <inheritdoc/> protected override void OnGamePadButtonDown(GamePadDevice device, GamePadButton button, Boolean repeat, ref RoutedEventData data) { if (GamePad.ConfirmButton == button) { var listBoxItem = ItemsControlUtil.FindContainer <ListBoxItem>(this, data.OriginalSource); if (listBoxItem != null) { HandleItemClicked(listBoxItem); data.Handled = true; } } else { if (!GamePad.UseAxisForDirectionalNavigation) { switch (button) { case GamePadButton.DPadLeft: if (PART_ScrollViewer != null) { PART_ScrollViewer.HandleKeyScrolling(Key.Left, ModifierKeys.None, ref data); } data.Handled = true; break; case GamePadButton.DPadRight: if (PART_ScrollViewer != null) { PART_ScrollViewer.HandleKeyScrolling(Key.Right, ModifierKeys.None, ref data); } data.Handled = true; break; case GamePadButton.DPadUp: if (SelectionMode == SelectionMode.Single) { MoveSelectedItem(FocusNavigationDirection.Up); } data.Handled = true; break; case GamePadButton.DPadDown: if (SelectionMode == SelectionMode.Single) { MoveSelectedItem(FocusNavigationDirection.Down); } data.Handled = true; break; } } } base.OnGamePadButtonDown(device, button, repeat, ref data); }
/// <summary> /// Moves the selected item in the specified direction. /// </summary> private void MoveSelectedItem(FocusNavigationDirection direction, ModifierKeys modifiers = ModifierKeys.None) { var selection = Keyboard.GetFocusedElement(View) as UIElement; if (selection != null && selection.MoveFocus(direction)) { var focused = Keyboard.GetFocusedElement(View) as UIElement; var listBoxItem = ItemsControlUtil.FindContainer <ListBoxItem>(this, focused); if (listBoxItem != null && (modifiers & ModifierKeys.Control) != ModifierKeys.Control) { HandleItemClickedAndScrollIntoView(listBoxItem); } } }
/// <inheritdoc/> protected override void OnGamePadButtonDown(GamePadDevice device, GamePadButton button, Boolean repeat, RoutedEventData data) { if (GamePad.ConfirmButton == button) { var listBoxItem = ItemsControlUtil.FindContainer <ListBoxItem>(this, data.OriginalSource); if (listBoxItem != null) { HandleItemClicked(listBoxItem); data.Handled = true; } } else { switch (button) { case GamePadButton.LeftStickLeft: PART_ScrollViewer?.LineLeft(); data.Handled = true; break; case GamePadButton.LeftStickRight: PART_ScrollViewer?.LineRight(); data.Handled = true; break; case GamePadButton.LeftStickUp: if (SelectionMode == SelectionMode.Single) { MoveSelectedItem(FocusNavigationDirection.Up); } data.Handled = true; break; case GamePadButton.LeftStickDown: if (SelectionMode == SelectionMode.Single) { MoveSelectedItem(FocusNavigationDirection.Down); } data.Handled = true; break; } } base.OnGamePadButtonDown(device, button, repeat, data); }
/// <summary> /// Performs tab navigation while focus is within the drop down. /// </summary> private void PerformTabNavigation(Key key, ModifierKeys modifiers) { var shift = ((modifiers & ModifierKeys.Shift) == ModifierKeys.Shift); var ctrl = ((modifiers & ModifierKeys.Control) == ModifierKeys.Control); var focused = Keyboard.GetFocusedElement(View) as UIElement; if (FocusNavigator.PerformNavigation(View, focused, shift ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next, ctrl)) { focused = Keyboard.GetFocusedElement(View) as UIElement; var container = (focused == null) ? null : ItemsControlUtil.FindContainer <ComboBoxItem>(this, focused); if (container != null) { ItemsControlUtil.ScrollItemIntoView <ComboBoxItem>(this, PART_ScrollViewer, container); } } }
/// <summary> /// Moves keyboard focus the specified number of steps away from the currently focused item. /// </summary> /// <param name="step">The number of steps by which to move focus.</param> private void MoveItemFocus(Int32 step) { var selectedContainer = ItemsControlUtil.FindFocusedContainer <ComboBoxItem>(this); var selectedIndex = (selectedContainer == null) ? -1 : ItemContainers.IndexOf(selectedContainer); var targetIndex = selectedIndex + step; if (targetIndex < 0 || targetIndex >= Items.Count) { return; } var targetContainer = ItemContainers[targetIndex] as UIElement; if (targetContainer == null) { return; } targetContainer.Focus(); ItemsControlUtil.ScrollItemIntoView <ComboBoxItem>(this, PART_ScrollViewer, targetContainer); }
/// <summary> /// Selects the item which currently has keyboard focus. /// </summary> private void SelectFocusedItem() { var container = ItemsControlUtil.FindFocusedContainer <ComboBoxItem>(this); SelectedIndex = (container == null) ? -1 : ItemContainers.IndexOf(container); }
/// <summary> /// Handles <see cref="Keyboard.KeyDownEvent"/> when the drop down is open. /// </summary> private void OnKeyDown_DropDownOpen(KeyboardDevice device, Key key, ModifierKeys modifiers, RoutedEventData data) { switch (key) { case Key.Tab: PerformTabNavigation(key, modifiers); data.Handled = true; break; case Key.Escape: IsDropDownOpen = false; data.Handled = true; break; case Key.Return: SelectFocusedItem(); IsDropDownOpen = false; data.Handled = true; break; case Key.Up: MoveItemFocus(-1); data.Handled = true; break; case Key.Down: MoveItemFocus(1); data.Handled = true; break; case Key.PageUp: var pageUpTarget = ItemsControlUtil.GetPageUpNext <ComboBoxItem>(this, PART_ScrollViewer); if (pageUpTarget != null && pageUpTarget.Focus()) { ItemsControlUtil.ScrollItemIntoView <ComboBoxItem>(this, PART_ScrollViewer, pageUpTarget, false); } data.Handled = true; break; case Key.PageDown: var pageDownTarget = ItemsControlUtil.GetPageDownNext <ComboBoxItem>(this, PART_ScrollViewer); if (pageDownTarget != null && pageDownTarget.Focus()) { ItemsControlUtil.ScrollItemIntoView <ComboBoxItem>(this, PART_ScrollViewer, pageDownTarget, false); } data.Handled = true; break; case Key.Home: var firstItem = ItemsControlUtil.GetFirstItem <ComboBoxItem>(this, PART_ScrollViewer); if (firstItem != null && firstItem.Focus()) { ItemsControlUtil.ScrollItemIntoView <ComboBoxItem>(this, PART_ScrollViewer, firstItem); } data.Handled = true; break; case Key.End: var lastItem = ItemsControlUtil.GetLastItem <ComboBoxItem>(this, PART_ScrollViewer); if (lastItem != null && lastItem.Focus()) { ItemsControlUtil.ScrollItemIntoView <ComboBoxItem>(this, PART_ScrollViewer, lastItem); } data.Handled = true; break; case Key.Left: PART_ScrollViewer?.LineLeft(); data.Handled = true; break; case Key.Right: PART_ScrollViewer?.LineRight(); data.Handled = true; break; } }
/// <summary> /// Selects the specified item and scrolls it into view. /// </summary> private void HandleItemClickedAndScrollIntoView(ListBoxItem item, Boolean buffer = true) { HandleItemClicked(item); ItemsControlUtil.ScrollItemIntoView <ListBoxItem>(this, PART_ScrollViewer, item, buffer); }
/// <inheritdoc/> protected override void OnKeyDown(KeyboardDevice device, Key key, ModifierKeys modifiers, RoutedEventData data) { switch (key) { case Key.Space: case Key.Return: if (key == Key.Return && !GetValue <Boolean>(KeyboardNavigation.AcceptsReturnProperty)) { break; } var listBoxItem = ItemsControlUtil.FindContainer <ListBoxItem>(this, data.OriginalSource); if (listBoxItem != null) { HandleItemClicked(listBoxItem); data.Handled = true; } break; case Key.Left: PART_ScrollViewer?.LineLeft(); data.Handled = true; break; case Key.Right: PART_ScrollViewer?.LineRight(); data.Handled = true; break; case Key.Up: if (SelectionMode == SelectionMode.Single) { MoveSelectedItem(FocusNavigationDirection.Up, modifiers); } data.Handled = true; break; case Key.Down: if (SelectionMode == SelectionMode.Single) { MoveSelectedItem(FocusNavigationDirection.Down, modifiers); } data.Handled = true; break; case Key.Home: var firstItem = ItemsControlUtil.GetFirstItem <ListBoxItem>(this, PART_ScrollViewer); if (firstItem != null && firstItem.Focus()) { HandleItemClickedAndScrollIntoView(firstItem); } data.Handled = true; break; case Key.End: var lastItem = ItemsControlUtil.GetLastItem <ListBoxItem>(this, PART_ScrollViewer); if (lastItem != null && lastItem.Focus()) { HandleItemClickedAndScrollIntoView(lastItem); } data.Handled = true; break; case Key.PageUp: var pageUpTarget = ItemsControlUtil.GetPageUpNext <ListBoxItem>(this, PART_ScrollViewer); if (pageUpTarget != null && pageUpTarget.Focus()) { HandleItemClickedAndScrollIntoView(pageUpTarget, false); } data.Handled = true; break; case Key.PageDown: var pageDownTarget = ItemsControlUtil.GetPageDownNext <ListBoxItem>(this, PART_ScrollViewer); if (pageDownTarget != null && pageDownTarget.Focus()) { HandleItemClickedAndScrollIntoView(pageDownTarget, false); } data.Handled = true; break; } base.OnKeyDown(device, key, modifiers, data); }