diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-08-25 17:50:22 +0300 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-08-25 17:50:22 +0300 |
| commit | 9bc0807514a69d97fceab11d77bee02aff4eb3d9 (patch) | |
| tree | 2c5ad002ab84443945943adc2ab531ce6fccda22 /Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs | |
| parent | 26b6bf34090634edf23ed5ed1785560c024da02c (diff) | |
| parent | 642dbff4c449d268d18ec4ca7f2ff267876dce14 (diff) | |
| download | Tango-9bc0807514a69d97fceab11d77bee02aff4eb3d9.tar.gz Tango-9bc0807514a69d97fceab11d77bee02aff4eb3d9.zip | |
Merge branch 'master' of https://twinetfs.visualstudio.com/Tango/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs')
| -rw-r--r-- | Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs | 317 |
1 files changed, 95 insertions, 222 deletions
diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs index f9d65bd2b..8fc6483e9 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs +++ b/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs @@ -1,104 +1,63 @@ using System; +using System.Collections; using System.Collections.ObjectModel; +using System.ComponentModel; using System.Diagnostics; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; +using System.Linq; using System.Windows.Media; using System.Windows.Threading; namespace Tango.SharedUI.Controls { [TemplatePart(Name = SearchComboBox.PartEditor, Type = typeof(System.Windows.Controls.TextBox))] - [TemplatePart(Name = SearchComboBox.PartPopup, Type = typeof(Popup))] public class SearchComboBox : ComboBox { public const string PartEditor = "Search"; - public const string PartPopup = "PART_Popup"; - private int _savedSelectedIndex = -1; - private bool _editorMouseLeaveFlag = false; - #region Properties - - private TextBox _editor; - - public TextBox Editor - { - get { return _editor; } - set { _editor = value; } - } - - - private Popup _popup; - - public Popup Popup - { - get { return _popup; } - set { _popup = value; } - } - - private DispatcherTimer _fetchTimer; - - public DispatcherTimer FetchTimer - { - get { return _fetchTimer; } - set { _fetchTimer = value; } - } - + private TextBox _textBox; + private ListBox _listBox; + private ICollectionView _view; - private string _searchText = ""; - /// <summary> - /// Gets or sets the search text of TextBox. - /// </summary> - public string SearchText + #region Properties + public bool IsOpened { - get { return _searchText; } - set - { - if(_searchText != value && value != null) - { - _searchText = value; - } - - } + get { return (bool)GetValue(IsOpenedProperty); } + set { SetValue(IsOpenedProperty, value); } } + public static readonly DependencyProperty IsOpenedProperty = + DependencyProperty.Register("IsOpened", typeof(bool), typeof(SearchComboBox), new PropertyMetadata(false, (d, e) => (d as SearchComboBox).OnIsOpenedChanged())); - public ListCollectionView SearchItemsList + public String SearchProperty { - get { return (ListCollectionView)GetValue(SearchItemsListProperty); } - set { SetValue(SearchItemsListProperty, value); } + get { return (String)GetValue(SearchPropertyProperty); } + set { SetValue(SearchPropertyProperty, value); } } - /// <summary> - /// The search items list property for popup items list - /// </summary> - public static readonly DependencyProperty SearchItemsListProperty = - DependencyProperty.Register("SearchItemsList", typeof(ListCollectionView), typeof(SearchComboBox), new PropertyMetadata(default(ObservableCollection<string>))); - + public static readonly DependencyProperty SearchPropertyProperty = + DependencyProperty.Register("SearchProperty", typeof(String), typeof(SearchComboBox), new PropertyMetadata(null)); - public string SearchParam + public String SearchFilter { - get { return (string)GetValue(SearchParamProperty); } - set { SetValue(SearchParamProperty, value); } + get { return (String)GetValue(SearchFilterProperty); } + set { SetValue(SearchFilterProperty, value); } } + public static readonly DependencyProperty SearchFilterProperty = + DependencyProperty.Register("SearchFilter", typeof(String), typeof(SearchComboBox), new PropertyMetadata(null, (d, e) => (d as SearchComboBox).OnFilterChanged())); - public static readonly DependencyProperty SearchParamProperty = - DependencyProperty.Register("SearchParam", typeof(string), typeof(SearchComboBox), new FrameworkPropertyMetadata("")); - - public System.Collections.IList SourceItems + public IEnumerable ListItemsSource { - get { return (System.Collections.IList)GetValue(SourceItemsProperty); } - set { SetValue(SourceItemsProperty, value); } + get { return (IEnumerable)GetValue(ListItemsSourceProperty); } + set { SetValue(ListItemsSourceProperty, value); } } - - public static readonly DependencyProperty SourceItemsProperty = - DependencyProperty.Register("SourceItems", typeof(System.Collections.IList), typeof(SearchComboBox), new PropertyMetadata(default(System.Collections.IList))); - + public static readonly DependencyProperty ListItemsSourceProperty = + DependencyProperty.Register("ListItemsSource", typeof(IEnumerable), typeof(SearchComboBox), new PropertyMetadata(null)); #endregion - - #region Constructors static SearchComboBox() @@ -106,203 +65,117 @@ namespace Tango.SharedUI.Controls DefaultStyleKeyProperty.OverrideMetadata(typeof(SearchComboBox), new FrameworkPropertyMetadata(typeof(SearchComboBox))); } - public SearchComboBox() - { - - } - #endregion //Constructors - - #region override - protected override void OnLostMouseCapture(MouseEventArgs e) - { - if (Mouse.Captured == null) - { - if (e.OriginalSource == this) - { - //SetPopupState(); - } - else if (IsDropDownOpen) - { - Mouse.Capture(this, CaptureMode.SubTree); - } - } - - base.OnLostMouseCapture(e); - } - - /// <summary> - /// Responds to a <see cref="T:System.Windows.Controls.ComboBox" /> selection change by raising a <see cref="E:System.Windows.Controls.Primitives.Selector.SelectionChanged" /> event. - /// Change selection only on click on item - /// </summary> - /// <param name="e">Provides data for <see cref="T:System.Windows.Controls.SelectionChangedEventArgs" />.</param> - protected override void OnSelectionChanged(SelectionChangedEventArgs e) - { - if (Editor == null || !Editor.IsKeyboardFocused || ( Editor.IsKeyboardFocused && _editorMouseLeaveFlag ) ) - { - base.OnSelectionChanged(e); - if (e.AddedItems.Count != 0 && SelectedIndex != this.SourceItems.IndexOf(e.AddedItems[0])) - { - SelectedValue = e.AddedItems[0]; - } - } - e.Handled = true; - } - - - #endregion - #region Initialization - - void InitSelectedList() - { - if (SearchItemsList == null) - { - SearchItemsList = new ListCollectionView(this.SourceItems); - if (String.IsNullOrEmpty(SearchParam)) - SearchItemsList.Filter = null; - else - { - SearchItemsList.Filter = (ob) => - { - var prop = ob.GetType().GetProperty(SearchParam); - if (prop == null) - { - return true; - } - string value = prop.GetValue(ob, null) as string; - return value != null && (String.IsNullOrEmpty(SearchText) || value.ToLower().Contains(SearchText.ToLower())); - }; - } - Binding mbinding = new Binding("SearchItems"); - mbinding.Mode = BindingMode.Default; - mbinding.Source = this; - mbinding.Path = new PropertyPath("SearchItemsList"); - - SetBinding(ComboBox.ItemsSourceProperty, mbinding); - } - } + /// <summary> /// When overridden in a derived class, is invoked whenever application code or internal processes call <see cref="M:System.Windows.FrameworkElement.ApplyTemplate" />. /// </summary> public override void OnApplyTemplate() { base.OnApplyTemplate(); - - var binding1 = BindingOperations.GetBinding(this, ComboBox.ItemsSourceProperty); - SetBinding(SearchComboBox.SourceItemsProperty, binding1); - Popup = Template.FindName(PartPopup, this) as Popup; - - if (Popup != null) + + _textBox = GetTemplateChild(PartEditor) as TextBox; + if(_textBox != null) { - Popup.StaysOpen = false; - Popup.Opened += OnPopupOpened; - Popup.Closed += OnPopupClosed; - + _textBox.PreviewKeyDown += _textBox_KeyDown; } - Editor = Template.FindName(PartEditor, this) as TextBox; - if(Editor != null) + _listBox = GetTemplateChild("list") as ListBox; + if(_listBox != null) { - Editor.TextChanged += OnEditorTextChanged; - Editor.MouseLeave += Editor_MouseLeave; - Editor.MouseEnter += Editor_MouseEnter; + _listBox.PreviewKeyDown += _listBox_PreviewKeyDown; + _listBox.PreviewMouseLeftButtonUp += _listBox_PreviewMouseLeftButtonUp; } } #endregion - #region EventHandlers - - private void Popup_KeyDown(object sender, KeyEventArgs e) + #region Event Handlers + private void _listBox_PreviewKeyDown(object sender, KeyEventArgs e) { - if (Editor != null ) + if (e.Key == Key.Return) { - Editor.Focus(); - Keyboard.Focus(Editor); + IsOpened = false; + SelectedItem = _listBox.SelectedItem; } } - private void OnPopupOpened(object sender, EventArgs e) + private void _textBox_KeyDown(object sender, KeyEventArgs e) { - SearchText = ""; - InitSelectedList(); - if (Editor != null ) + if (e.Key == Key.Down) { - Editor.Text = ""; - Editor.Focus(); - Editor.SelectionStart = 0; - Keyboard.Focus(Editor); + _listBox.SelectedIndex = 0; + _listBox.Focus(); + Keyboard.Focus(_listBox); } - _savedSelectedIndex = SelectedIndex; } - /// <summary> - /// Called when [popup closed]. - /// Selection Index/Value will be set according to unfiltered whole list - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> - private void OnPopupClosed(object sender, EventArgs e) + private void _listBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { - if(SelectedIndex == -1 && _savedSelectedIndex >=0)// selection item was set to null for filtering but not selected, return to prev value - { - SearchText = ""; - SearchItemsList.Refresh(); - SelectedValue = SearchItemsList.GetItemAt(_savedSelectedIndex); - } - if(this.SourceItems.Count != SearchItemsList.Count)//selection was changed on filtered list - replace to real selection index + if (!(e.OriginalSource is Thumb)) { - var selvalue = SelectedValue; - SearchText = ""; - SearchItemsList.Refresh(); - SelectedValue = selvalue; + IsOpened = false; + SelectedItem = _listBox.SelectedItem; } - _savedSelectedIndex = -1; } - private void OnEditorTextChanged(object sender, TextChangedEventArgs e) + private async void OnIsOpenedChanged() { - if (FetchTimer == null) + if (IsOpened) { - FetchTimer = new DispatcherTimer(); - FetchTimer.Interval = TimeSpan.FromMilliseconds(100); - FetchTimer.Tick += OnFetchTimerTick; + _listBox.SelectedItem = SelectedItem; + SearchFilter = ""; + await Task.Delay(100); + _textBox.Focus(); + + Keyboard.Focus(_textBox); } - - FetchTimer.IsEnabled = true; - FetchTimer.Start(); - } - - private void Editor_MouseEnter(object sender, MouseEventArgs e) - { - _editorMouseLeaveFlag = false; } - private void Editor_MouseLeave(object sender, MouseEventArgs e) - { - _editorMouseLeaveFlag = true; - } - - private void OnFetchTimerTick(object sender, EventArgs e) + private void OnFilterChanged() { - FetchTimer.IsEnabled = false; - FetchTimer.Stop(); - SearchText = Editor.Text; - OnTextChanged(); + _view?.Refresh(); } - public virtual void OnTextChanged() + #endregion + #region Override + + protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue) { - if (SearchItemsList != null) - { - SearchItemsList.Refresh(); - } - if(SearchItemsList.Count > 0 && SelectedIndex != -1) + base.OnItemsSourceChanged(oldValue, newValue); + + if (ItemsSource != null) { - SelectedIndex = -1;// trick: all filtered items are displayed only with SelectedIndex = -1 , otherwise it is displayed 1 less + ListItemsSource = ItemsSource.Cast<Object>().ToList(); + + _view = CollectionViewSource.GetDefaultView(ListItemsSource); + _view.Filter = (x) => + { + if (String.IsNullOrWhiteSpace(SearchFilter) || SearchFilter == null) return true; + + if (x != null) + { + var prop = x.GetType().GetProperty(SearchProperty); + + // var prop = x.GetType().GetProperty(SearchProperty, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly); + if (prop != null) + { + String propValue = prop.GetValue(x).ToString(); + return propValue.ToLower().Contains(SearchFilter.ToLower()); + } + } + + return false; + }; } } + protected override void OnSelectionChanged(SelectionChangedEventArgs e) + { + base.OnSelectionChanged(e); + } + #endregion + } } |
