diff options
| author | Victoria Plitt <Victoria.Plitt@twine-s.com> | 2020-08-05 00:28:12 +0300 |
|---|---|---|
| committer | Victoria Plitt <Victoria.Plitt@twine-s.com> | 2020-08-05 00:28:12 +0300 |
| commit | 054b6ca55142fae5bb30a9b8f3301f7e71a92296 (patch) | |
| tree | 13cd2dd8ba72af9b78a98ac56d1785a423be0e89 /Software/Visual_Studio/Tango.SharedUI/Controls | |
| parent | 064bb0517aa7f8a1906761ae099cf44b785cff9f (diff) | |
| download | Tango-054b6ca55142fae5bb30a9b8f3301f7e71a92296.tar.gz Tango-054b6ca55142fae5bb30a9b8f3301f7e71a92296.zip | |
Added a new control SearchComboBox. Refactoring code filter of RmlsCollectionView.
Related Work Items: #3286
Diffstat (limited to 'Software/Visual_Studio/Tango.SharedUI/Controls')
| -rw-r--r-- | Software/Visual_Studio/Tango.SharedUI/Controls/PopupWithKeyboardFocus.cs | 42 | ||||
| -rw-r--r-- | Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs | 308 |
2 files changed, 350 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/PopupWithKeyboardFocus.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/PopupWithKeyboardFocus.cs new file mode 100644 index 000000000..9426b95cf --- /dev/null +++ b/Software/Visual_Studio/Tango.SharedUI/Controls/PopupWithKeyboardFocus.cs @@ -0,0 +1,42 @@ +using MaterialDesignThemes.Wpf; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Interop; + +namespace Tango.SharedUI.Controls +{ + public class PopupWithKeyboardFocus: ComboBoxPopup + { + [DllImport("user32.dll")] + static extern IntPtr SetActiveWindow(IntPtr hWnd); + + static PopupWithKeyboardFocus() + { + EventManager.RegisterClassHandler( + typeof(PopupWithKeyboardFocus), + Popup.PreviewGotKeyboardFocusEvent, + new KeyboardFocusChangedEventHandler(OnPreviewGotKeyboardFocus), + true); + } + + private static void OnPreviewGotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e) + { + var textBox = e.NewFocus as TextBoxBase; + if (textBox != null) + { + var hwndSource = PresentationSource.FromVisual(textBox) as HwndSource; + if (hwndSource != null) + { + SetActiveWindow(hwndSource.Handle); + } + } + } + } +} diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs new file mode 100644 index 000000000..f9d65bd2b --- /dev/null +++ b/Software/Visual_Studio/Tango.SharedUI/Controls/SearchComboBox.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Input; +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 string _searchText = ""; + /// <summary> + /// Gets or sets the search text of TextBox. + /// </summary> + public string SearchText + { + get { return _searchText; } + set + { + if(_searchText != value && value != null) + { + _searchText = value; + } + + } + } + + public ListCollectionView SearchItemsList + { + get { return (ListCollectionView)GetValue(SearchItemsListProperty); } + set { SetValue(SearchItemsListProperty, 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 string SearchParam + { + get { return (string)GetValue(SearchParamProperty); } + set { SetValue(SearchParamProperty, value); } + } + + public static readonly DependencyProperty SearchParamProperty = + DependencyProperty.Register("SearchParam", typeof(string), typeof(SearchComboBox), new FrameworkPropertyMetadata("")); + + public System.Collections.IList SourceItems + { + get { return (System.Collections.IList)GetValue(SourceItemsProperty); } + set { SetValue(SourceItemsProperty, value); } + } + + public static readonly DependencyProperty SourceItemsProperty = + DependencyProperty.Register("SourceItems", typeof(System.Collections.IList), typeof(SearchComboBox), new PropertyMetadata(default(System.Collections.IList))); + + + #endregion + + + #region Constructors + + static SearchComboBox() + { + 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) + { + Popup.StaysOpen = false; + Popup.Opened += OnPopupOpened; + Popup.Closed += OnPopupClosed; + + } + Editor = Template.FindName(PartEditor, this) as TextBox; + if(Editor != null) + { + Editor.TextChanged += OnEditorTextChanged; + Editor.MouseLeave += Editor_MouseLeave; + Editor.MouseEnter += Editor_MouseEnter; + } + } + + #endregion + + #region EventHandlers + + private void Popup_KeyDown(object sender, KeyEventArgs e) + { + if (Editor != null ) + { + Editor.Focus(); + Keyboard.Focus(Editor); + } + } + + private void OnPopupOpened(object sender, EventArgs e) + { + SearchText = ""; + InitSelectedList(); + if (Editor != null ) + { + Editor.Text = ""; + Editor.Focus(); + Editor.SelectionStart = 0; + Keyboard.Focus(Editor); + } + _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) + { + 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 + { + var selvalue = SelectedValue; + SearchText = ""; + SearchItemsList.Refresh(); + SelectedValue = selvalue; + } + _savedSelectedIndex = -1; + } + + private void OnEditorTextChanged(object sender, TextChangedEventArgs e) + { + if (FetchTimer == null) + { + FetchTimer = new DispatcherTimer(); + FetchTimer.Interval = TimeSpan.FromMilliseconds(100); + FetchTimer.Tick += OnFetchTimerTick; + } + + 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) + { + FetchTimer.IsEnabled = false; + FetchTimer.Stop(); + SearchText = Editor.Text; + OnTextChanged(); + } + + public virtual void OnTextChanged() + { + if (SearchItemsList != null) + { + SearchItemsList.Refresh(); + } + if(SearchItemsList.Count > 0 && SelectedIndex != -1) + { + SelectedIndex = -1;// trick: all filtered items are displayed only with SelectedIndex = -1 , otherwise it is displayed 1 less + } + } + + #endregion + } +} |
