using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Tango.Core.Commands; using System.ComponentModel; using System.Windows.Controls.Primitives; using System.Windows.Threading; using System.Diagnostics; namespace Tango.SharedUI.Controls { internal sealed class MultiSelectComboBoxTemplateSelector : DataTemplateSelector { public override DataTemplate SelectTemplate(object item, DependencyObject container) { FrameworkElement element = container as FrameworkElement; if (element != null && item != null && item is MultiSelectComboBoxItem) return element.FindResource("CheckItem") as DataTemplate; return element.FindResource("SearchItem") as DataTemplate; ; } } [TemplatePart(Name = MultiSelectComboBox.PartEditor, Type = typeof(TextBox))] [TemplatePart(Name = MultiSelectComboBox.PartPopup, Type = typeof(Popup))] public class MultiSelectComboBox : Control { #region Fields public const string PartEditor = "Edit_PART"; public const string PartPopup = "MultiSel_Popup"; private ItemsControl _items_control; private bool _isLoaded; #endregion #region "Constructors" static MultiSelectComboBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(typeof(MultiSelectComboBox))); } public MultiSelectComboBox() : base() { SelectedItemsList = new ObservableCollection(); RemoveAllCommand = new RelayCommand(RemoveAllSelectedItems, CanRemoveAllSelectedItems); RemoveItemCommand = new RelayCommand(RemoveSelectedItem); AddItemCommand = new RelayCommand(AddSelectedItem); SearchText = new MultiSelectComboBoxSearchItem(); Loaded += MultiSelectComboBox_Loaded; _isLoaded = false; } #endregion #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; } } public ObservableCollection SelectedItemsList { get { return (ObservableCollection)GetValue(SelectedItemsListProperty); } set { SetValue(SelectedItemsListProperty, value); } } public static readonly DependencyProperty SelectedItemsListProperty = DependencyProperty.Register("SelectedItemsList", typeof(ObservableCollection), typeof(MultiSelectComboBox), new PropertyMetadata(default(ObservableCollection))); public ListCollectionView SearchItemsList { get { return (ListCollectionView)GetValue(SearchItemsListProperty); } set { SetValue(SearchItemsListProperty, value); } } /// /// The search items list property for popup items list /// public static readonly DependencyProperty SearchItemsListProperty = DependencyProperty.Register("SearchItemsList", typeof(ListCollectionView), typeof(MultiSelectComboBox), new PropertyMetadata(default(ObservableCollection))); public ObservableCollection Items { get { return (ObservableCollection)GetValue(ItemsProperty); } set { SetValue(ItemsProperty, value); } } public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection), typeof(MultiSelectComboBox), new PropertyMetadata(default(ObservableCollection))); public bool IsToggleChecked { get { return (bool)GetValue(IsToggleCheckedProperty); } set { SetValue(IsToggleCheckedProperty, value); } } public static readonly DependencyProperty IsToggleCheckedProperty = DependencyProperty.Register("IsToggleChecked", typeof(bool), typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(false)); private MultiSelectComboBoxSearchItem _searchText; /// /// Gets or sets the search text of TextBox. /// public MultiSelectComboBoxSearchItem SearchText { get { return _searchText; } set { _searchText = value; OnTextChanged(); } } #endregion private void MultiSelectComboBox_Loaded(object sender, RoutedEventArgs e) { if (!_isLoaded) { ToggleButton b2 = GetTemplateChild("MultiSelToggleButton") as ToggleButton; if (b2 != null) { // ct.LoadContent(); _items_control = b2.Template.FindName("SelectedItemsControl", b2) as ItemsControl; if (_items_control != null) { var wrapPanel = _items_control.FindChild(); if (wrapPanel != null) { _items_control.Bind(ItemsControl.HeightProperty, wrapPanel, WrapPanel.ActualHeightProperty, BindingMode.OneWay); _isLoaded = true; var searchItem =(_items_control.ItemContainerGenerator.ContainerFromItem(SearchText)); Editor = searchItem.FindVisualChildren< TextBox>().FirstOrDefault(x => x.Name == PartEditor); if (Editor != null) { Editor.TextChanged += OnEditorTextChanged; Editor.PreviewKeyDown += OnEditorKeyDown; Editor.LostFocus += OnEditorLostFocus; Editor.GotFocus += OnEditorGotFocus; } } } this.GotFocus += SelTextBox_GotFocus; } } } void OnTextChanged() { if(SearchItemsList != null) { if (String.IsNullOrEmpty(SearchText.Text)) SearchItemsList.Filter = null; else SearchItemsList.Filter = new Predicate(o => (((string)o).ToLower().Contains(SearchText.Text.ToLower()))); } } /// /// When overridden in a derived class, is invoked whenever application code or internal processes call . /// public override void OnApplyTemplate() { base.OnApplyTemplate(); if (SelectedItemsList == null) SelectedItemsList = new ObservableCollection(); SelectedItemsList.Add(SearchText); SearchItemsList = new ListCollectionView(this.Items); Popup = Template.FindName(PartPopup, this) as Popup; if (Popup != null) { Popup.StaysOpen = false; Popup.Opened += OnPopupOpened; Popup.Closed += OnPopupClosed; } } private void OnEditorTextChanged(object sender, TextChangedEventArgs e) { if (FetchTimer == null) { FetchTimer = new DispatcherTimer(); FetchTimer.Interval = TimeSpan.FromMilliseconds(500); FetchTimer.Tick += OnFetchTimerTick; } FetchTimer.IsEnabled = false; FetchTimer.Stop(); IsToggleChecked = true; FetchTimer.IsEnabled = true; FetchTimer.Start(); } private void OnFetchTimerTick(object sender, EventArgs e) { FetchTimer.IsEnabled = false; FetchTimer.Stop(); SearchText.Text = Editor.Text; OnTextChanged(); } private void OnEditorKeyDown(object sender, KeyEventArgs e) { IsToggleChecked = true; } private void OnEditorLostFocus(object sender, RoutedEventArgs e) { if (!IsKeyboardFocusWithin) { IsToggleChecked = false; } } private void SelTextBox_GotFocus(object sender, RoutedEventArgs e) { Editor?.Focus(); } private void OnEditorGotFocus(object sender, RoutedEventArgs e) { IsToggleChecked = true; } private void OnPopupOpened(object sender, EventArgs e) { } private void OnPopupClosed(object sender, EventArgs e) { IsToggleChecked = false; } #region Commands /// /// The remove all command property for clear SelectedItemsList /// public static DependencyProperty RemoveAllCommandProperty = DependencyProperty.Register("RemoveAllCommand", typeof(RelayCommand), typeof(MultiSelectComboBox)); public RelayCommand RemoveAllCommand { get { return (RelayCommand)GetValue(RemoveAllCommandProperty); } private set { SetValue(RemoveAllCommandProperty, value); } } /// /// The remove item from SelectedItemsList command property /// public static DependencyProperty RemoveItemCommandProperty = DependencyProperty.Register("RemoveItemCommand", typeof(RelayCommand), typeof(MultiSelectComboBox)); public RelayCommand RemoveItemCommand { get { return (RelayCommand)GetValue(RemoveItemCommandProperty); } private set { SetValue(RemoveItemCommandProperty, value); } } /// /// The add item to SelectedItemsList command property /// public static DependencyProperty AddItemCommandProperty = DependencyProperty.Register("AddItemCommand", typeof(RelayCommand), typeof(MultiSelectComboBox)); public RelayCommand AddItemCommand { get { return (RelayCommand)GetValue(AddItemCommandProperty); } private set { SetValue(AddItemCommandProperty, value); } } /// /// Removes the selected item. /// /// The item. private void RemoveSelectedItem(IMultiSelectComboBoxItem item) { SelectedItemsList.Remove(item); RemoveAllCommand.RaiseCanExecuteChanged(); } /// /// Adds the selected item. /// /// The item. private void AddSelectedItem(string item) { if (SelectedItemsList.Any(x => (x as IMultiSelectComboBoxItem).Text == item)) return; SelectedItemsList.Insert(SelectedItemsList.Count - 1, new MultiSelectComboBoxItem(item)); RemoveAllCommand.RaiseCanExecuteChanged(); } /// /// Removes all selected items. /// private void RemoveAllSelectedItems() { int index = SelectedItemsList.Count - 2; while (index >= 0) { SelectedItemsList.RemoveAt(index--); } RemoveAllCommand.RaiseCanExecuteChanged(); } private bool CanRemoveAllSelectedItems() { return (SelectedItemsList != null && SelectedItemsList.Count > 1); } #endregion } }