using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Globalization; namespace HashCalculator.GUI { /// /// InputBar.xaml 的交互逻辑 /// [SuppressMessage("Microsoft.Performance", "CA1812")] internal partial class InputBar : UserControl { public static readonly DependencyProperty HintTextProperty = DependencyProperty.Register(nameof(HintText), typeof(string), typeof(InputBar), new FrameworkPropertyMetadata { BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }); public string? HintText { get => GetValue(HintTextProperty) as string; set => SetValue(HintTextProperty, value); } public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text), typeof(string), typeof(InputBar), new FrameworkPropertyMetadata { BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }); public string? Text { get => GetValue(TextProperty) as string; set => SetValue(TextProperty, value); } public static readonly DependencyProperty CollectionProperty = DependencyProperty.Register(nameof(Collection), typeof(IEnumerable), typeof(InputBar), new FrameworkPropertyMetadata { BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, CoerceValueCallback = (d, baseObject) => { var value = baseObject as IEnumerable; if (value?.Count() > 100) { value = value .Take(99) .Append(new InputEntry(InputEntryType.Path, $"Other {value.Count() - 50} items...", string.Empty)); } return value; } }); public IEnumerable? Collection { get => GetValue(CollectionProperty) as IEnumerable; set => SetValue(CollectionProperty, value); } public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(nameof(SelectedItem), typeof(InputEntry), typeof(InputBar), new FrameworkPropertyMetadata { BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, PropertyChangedCallback = (d, e) => { var self = (InputBar)d; self.OnSelectionChanged(); } }); public InputEntry? SelectedItem { get => GetValue(SelectedItemProperty) as InputEntry; set => SetValue(SelectedItemProperty, value); } public static readonly DependencyProperty SelectedIndexProperty = DependencyProperty.Register(nameof(SelectedIndex), typeof(int), typeof(InputBar), new FrameworkPropertyMetadata { BindsTwoWayByDefault = true, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, CoerceValueCallback = (d, baseObject) => { var self = (InputBar)d; return self.NormalizeIndex((int)baseObject); } }); public int SelectedIndex { get => (int)GetValue(SelectedIndexProperty); set => SetValue(SelectedIndexProperty, value); } public InputBar() { InitializeComponent(); } private void OnPreviewKeyDown(object sender, KeyEventArgs e) { switch (e.Key) { case Key.Down: SelectedIndex += 1; ListBox.ScrollIntoView(ListBox.SelectedItem); DropDown.IsOpen = true; break; case Key.Up: SelectedIndex -= 1; ListBox.ScrollIntoView(ListBox.SelectedItem); break; case Key.Escape: case Key.Enter: DropDown.IsOpen = false; break; default: DropDown.IsOpen = true; break; } } private void OnSelectionChanged() { if (SelectedItem != null) { Text = SelectedItem.ToString(); TextBox.Select(Text.Length, 0); } } private void OnLostFocus(object sender, RoutedEventArgs e) { DropDown.IsOpen = false; } private int NormalizeIndex(int rawIndex) { if (Collection == null) { return -1; } return Math.Min(Math.Max(rawIndex, -1), Collection.Count() - 1); } private void OnToggleDropDownButtonClick(object sender, RoutedEventArgs e) { TextBox.Focus(); TextBox.Select(Text?.Length ?? 0, 0); if (!DropDown.IsOpen) { DropDown.IsOpen = true; } } } }