From 55da255d86e55c9c4a01a6c21e3e387c1a5b8722 Mon Sep 17 00:00:00 2001 From: CommonGuy Date: Wed, 16 May 2018 10:43:26 +0200 Subject: [PATCH] Improve KeyDown behavior in DropDown --- src/Avalonia.Controls/DropDown.cs | 80 ++++++++++++++------------- src/Avalonia.Controls/DropDownItem.cs | 35 +++++++++++- 2 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/Avalonia.Controls/DropDown.cs b/src/Avalonia.Controls/DropDown.cs index 932179028e..5b7213257d 100644 --- a/src/Avalonia.Controls/DropDown.cs +++ b/src/Avalonia.Controls/DropDown.cs @@ -6,7 +6,6 @@ using Avalonia.Controls.Generators; using Avalonia.Controls.Primitives; using Avalonia.Controls.Shapes; using Avalonia.Input; -using Avalonia.Layout; using Avalonia.LogicalTree; using Avalonia.Media; using Avalonia.VisualTree; @@ -51,6 +50,7 @@ namespace Avalonia.Controls { FocusableProperty.OverrideDefaultValue(true); SelectedItemProperty.Changed.AddClassHandler(x => x.SelectedItemChanged); + KeyDownEvent.AddClassHandler(x => x.OnKeyDown, Interactivity.RoutingStrategies.Tunnel); } /// @@ -96,54 +96,46 @@ namespace Avalonia.Controls this.UpdateSelectionBoxItem(this.SelectedItem); } - protected override void OnGotFocus(GotFocusEventArgs e) - { - base.OnGotFocus(e); - - if (!e.Handled && e.NavigationMethod == NavigationMethod.Directional) - { - e.Handled = UpdateSelectionFromEventSource(e.Source); - } - } - /// protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); - if (!e.Handled) + if (e.Handled) + return; + + if (e.Key == Key.F4 || + ((e.Key == Key.Down || e.Key == Key.Up) && ((e.Modifiers & InputModifiers.Alt) != 0))) { - if (e.Key == Key.F4 || - ((e.Key == Key.Down || e.Key == Key.Up) && ((e.Modifiers & InputModifiers.Alt) != 0))) + IsDropDownOpen = !IsDropDownOpen; + e.Handled = true; + } + else if (IsDropDownOpen && e.Key == Key.Escape) + { + IsDropDownOpen = false; + e.Handled = true; + } + else if (IsDropDownOpen && e.Key == Key.Enter) + { + SelectFocusedItem(); + IsDropDownOpen = false; + e.Handled = true; + } + else if (!IsDropDownOpen) + { + if (e.Key == Key.Down) { - IsDropDownOpen = !IsDropDownOpen; + if (++SelectedIndex >= ItemCount) + SelectedIndex = 0; + e.Handled = true; } - else if (IsDropDownOpen && (e.Key == Key.Escape || e.Key == Key.Enter)) + else if (e.Key == Key.Up) { - IsDropDownOpen = false; - e.Handled = true; - } + if (--SelectedIndex < 0) + SelectedIndex = ItemCount - 1; - if (!IsDropDownOpen) - { - if (e.Key == Key.Down) - { - if (SelectedIndex == -1) - SelectedIndex = 0; - - if (++SelectedIndex >= ItemCount) - SelectedIndex = 0; - - e.Handled = true; - } - else if (e.Key == Key.Up) - { - if (--SelectedIndex < 0) - SelectedIndex = ItemCount - 1; - - e.Handled = true; - } + e.Handled = true; } } } @@ -230,5 +222,17 @@ namespace Avalonia.Controls SelectionBoxItem = item; } } + + private void SelectFocusedItem() + { + foreach (ItemContainerInfo dropdownItem in ItemContainerGenerator.Containers) + { + if (dropdownItem.ContainerControl.IsFocused) + { + SelectedIndex = dropdownItem.Index; + break; + } + } + } } } diff --git a/src/Avalonia.Controls/DropDownItem.cs b/src/Avalonia.Controls/DropDownItem.cs index 1a5cbb5014..3fd80c4562 100644 --- a/src/Avalonia.Controls/DropDownItem.cs +++ b/src/Avalonia.Controls/DropDownItem.cs @@ -1,12 +1,45 @@ // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using System; + namespace Avalonia.Controls { /// /// A selectable item in a . /// - public class DropDownItem : ListBoxItem + public class DropDownItem : ContentControl, ISelectable { + /// + /// Defines the property. + /// + public static readonly StyledProperty IsSelectedProperty = + AvaloniaProperty.Register(nameof(IsSelected)); + + /// + /// Initializes static members of the class. + /// + static DropDownItem() + { + FocusableProperty.OverrideDefaultValue(true); + IsFocusedProperty.Changed.Subscribe(x => + { + var sender = x.Sender as IControl; + + if (sender != null) + { + ((IPseudoClasses)sender.Classes).Set(":selected", (bool)x.NewValue); + } + }); + } + + /// + /// Gets or sets the selection state of the item. + /// + public bool IsSelected + { + get { return GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } } }