123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- using System;
- using System.ComponentModel;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Input;
- using System.Windows.Threading;
- using HandyControl.Data;
- using HandyControl.Interactivity;
- namespace HandyControl.Controls;
- [TemplatePart(Name = ElementPanel, Type = typeof(Panel))]
- [TemplatePart(Name = ElementSelectAll, Type = typeof(CheckComboBoxItem))]
- public class CheckComboBox : ListBox
- {
- private const string ElementPanel = "PART_Panel";
- private const string ElementSelectAll = "PART_SelectAll";
- private Panel _panel;
- private CheckComboBoxItem _selectAllItem;
- private bool _isInternalAction;
- public static readonly DependencyProperty MaxDropDownHeightProperty =
- System.Windows.Controls.ComboBox.MaxDropDownHeightProperty.AddOwner(typeof(CheckComboBox),
- new FrameworkPropertyMetadata(SystemParameters.PrimaryScreenHeight / 3));
- [Bindable(true), Category("Layout")]
- [TypeConverter(typeof(LengthConverter))]
- public double MaxDropDownHeight
- {
- get => (double) GetValue(MaxDropDownHeightProperty);
- set => SetValue(MaxDropDownHeightProperty, value);
- }
- public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register(
- nameof(IsDropDownOpen), typeof(bool), typeof(CheckComboBox), new PropertyMetadata(ValueBoxes.FalseBox, OnIsDropDownOpenChanged));
- private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var ctl = (CheckComboBox) d;
- if (!(bool) e.NewValue)
- {
- ctl.Dispatcher.BeginInvoke(new Action(() =>
- {
- Mouse.Capture(null);
- }), DispatcherPriority.Send);
- }
- }
- public bool IsDropDownOpen
- {
- get => (bool) GetValue(IsDropDownOpenProperty);
- set => SetValue(IsDropDownOpenProperty, ValueBoxes.BooleanBox(value));
- }
- public static readonly DependencyProperty TagStyleProperty = DependencyProperty.Register(
- nameof(TagStyle), typeof(Style), typeof(CheckComboBox), new PropertyMetadata(default(Style)));
- public Style TagStyle
- {
- get => (Style) GetValue(TagStyleProperty);
- set => SetValue(TagStyleProperty, value);
- }
- public static readonly DependencyProperty TagSpacingProperty = DependencyProperty.Register(
- nameof(TagSpacing), typeof(double), typeof(CheckComboBox), new PropertyMetadata(ValueBoxes.Double0Box));
- public double TagSpacing
- {
- get => (double) GetValue(TagSpacingProperty);
- set => SetValue(TagSpacingProperty, value);
- }
- public static readonly DependencyProperty ShowSelectAllButtonProperty = DependencyProperty.Register(
- nameof(ShowSelectAllButton), typeof(bool), typeof(CheckComboBox), new PropertyMetadata(ValueBoxes.FalseBox));
- public bool ShowSelectAllButton
- {
- get => (bool) GetValue(ShowSelectAllButtonProperty);
- set => SetValue(ShowSelectAllButtonProperty, ValueBoxes.BooleanBox(value));
- }
- public CheckComboBox()
- {
- AddHandler(Controls.Tag.ClosedEvent, new RoutedEventHandler(Tags_OnClosed));
- CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
- {
- SetCurrentValue(SelectedValueProperty, null);
- SetCurrentValue(SelectedItemProperty, null);
- SetCurrentValue(SelectedIndexProperty, -1);
- SelectedItems.Clear();
- }));
- }
- public override void OnApplyTemplate()
- {
- if (_selectAllItem != null)
- {
- _selectAllItem.Selected -= SelectAllItem_Selected;
- _selectAllItem.Unselected -= SelectAllItem_Unselected;
- }
- base.OnApplyTemplate();
- _panel = GetTemplateChild(ElementPanel) as Panel;
- _selectAllItem = GetTemplateChild(ElementSelectAll) as CheckComboBoxItem;
- if (_selectAllItem != null)
- {
- _selectAllItem.Selected += SelectAllItem_Selected;
- _selectAllItem.Unselected += SelectAllItem_Unselected;
- }
- UpdateTags();
- }
- protected override void OnSelectionChanged(SelectionChangedEventArgs e)
- {
- UpdateTags();
- base.OnSelectionChanged(e);
- }
- protected override bool IsItemItsOwnContainerOverride(object item) => item is CheckComboBoxItem;
- protected override DependencyObject GetContainerForItemOverride() => new CheckComboBoxItem();
- protected override void OnDisplayMemberPathChanged(string oldDisplayMemberPath, string newDisplayMemberPath) => UpdateTags();
- private void Tags_OnClosed(object sender, RoutedEventArgs e)
- {
- if (e.OriginalSource is Tag tag)
- {
- SelectedItems.Remove(tag.Tag);
- _panel.Children.Remove(tag);
- }
- }
- private void SwitchAllItems(bool selected)
- {
- if (_isInternalAction) return;
- _isInternalAction = true;
- if (!selected)
- {
- UnselectAll();
- }
- else
- {
- SelectAll();
- }
- _isInternalAction = false;
- UpdateTags();
- }
- private void SelectAllItem_Selected(object sender, RoutedEventArgs e) => SwitchAllItems(true);
- private void SelectAllItem_Unselected(object sender, RoutedEventArgs e) => SwitchAllItems(false);
- private void UpdateTags()
- {
- if (_panel == null || _isInternalAction) return;
- if (_selectAllItem != null)
- {
- _isInternalAction = true;
- _selectAllItem.SetCurrentValue(IsSelectedProperty, Items.Count > 0 && SelectedItems.Count == Items.Count);
- _isInternalAction = false;
- }
- _panel.Children.Clear();
- foreach (var item in SelectedItems)
- {
- var tag = new Tag
- {
- Style = TagStyle,
- Tag = item
- };
- if (ItemsSource != null)
- {
- tag.SetBinding(ContentControl.ContentProperty, new Binding(DisplayMemberPath) { Source = item });
- }
- else
- {
- tag.Content = IsItemItsOwnContainerOverride(item) ? ((CheckComboBoxItem) item).Content : item;
- }
- _panel.Children.Add(tag);
- }
- }
- }
|