using System; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Threading; namespace SWS.CAD.Views.CustomControl { public class MultiSelectComboBox : ListBox { private const string PART_Popup = "PART_Popup"; private const string PART_CheckBoxAll = "PART_CheckBoxAll"; public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(MultiSelectComboBox), new PropertyMetadata(false)); public static readonly DependencyProperty MaxDropDownHeightProperty = DependencyProperty.Register("MaxDropDownHeight", typeof(double), typeof(MultiSelectComboBox), new PropertyMetadata(SystemParameters.PrimaryScreenHeight / 3)); public static readonly DependencyProperty SelectAllContentProperty = DependencyProperty.Register("SelectAllContent", typeof(object), typeof(MultiSelectComboBox), new PropertyMetadata("全选")); public static readonly DependencyProperty IsSelectAllActiveProperty = DependencyProperty.Register("IsSelectAllActive", typeof(bool), typeof(MultiSelectComboBox), new PropertyMetadata(false)); public static readonly DependencyProperty DelimiterProperty = DependencyProperty.Register("Delimiter", typeof(string), typeof(MultiSelectComboBox), new PropertyMetadata(",")); public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MultiSelectComboBox), new PropertyMetadata(string.Empty, OnTextChanged)); private bool _ignoreTextValueChanged; private MultiSelectComboBoxItem _multiSelectComboBoxItem; private Popup _popup; public bool IsDropDownOpen { get => (bool)GetValue(IsDropDownOpenProperty); set => SetValue(IsDropDownOpenProperty, value); } [Bindable(true)] [Category("Layout")] [TypeConverter(typeof(LengthConverter))] public double MaxDropDownHeight { get => (double)GetValue(MaxDropDownHeightProperty); set => SetValue(MaxDropDownHeightProperty, value); } public object SelectAllContent { get => GetValue(SelectAllContentProperty); set => SetValue(SelectAllContentProperty, value); } public bool IsSelectAllActive { get => (bool)GetValue(IsSelectAllActiveProperty); set => SetValue(IsSelectAllActiveProperty, value); } public string Delimiter { get => (string)GetValue(DelimiterProperty); set => SetValue(DelimiterProperty, value); } public string Text { get => (string)GetValue(TextProperty); set => SetValue(TextProperty, value); } private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var MultiSelectComboBox = (MultiSelectComboBox)d; if (!(bool)e.NewValue) MultiSelectComboBox.Dispatcher.BeginInvoke(new Action(() => { Mouse.Capture(null); }), DispatcherPriority.Send); } private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { } protected override bool IsItemItsOwnContainerOverride(object item) { return item is MultiSelectComboBoxItem; } protected override DependencyObject GetContainerForItemOverride() { return new MultiSelectComboBoxItem(); } protected override void OnSelectionChanged(SelectionChangedEventArgs e) { UpdateText(); base.OnSelectionChanged(e); } public override void OnApplyTemplate() { base.OnApplyTemplate(); _popup = GetTemplateChild(PART_Popup) as Popup; _multiSelectComboBoxItem = GetTemplateChild(PART_CheckBoxAll) as MultiSelectComboBoxItem; _multiSelectComboBoxItem.Selected += _MultiSelectComboBoxItem_Selected; _multiSelectComboBoxItem.Unselected += _MultiSelectComboBoxItem_Unselected; } private void _MultiSelectComboBoxItem_Unselected(object sender, RoutedEventArgs e) { if (_ignoreTextValueChanged) return; _ignoreTextValueChanged = true; UnselectAll(); _ignoreTextValueChanged = false; UpdateText(); } private void _MultiSelectComboBoxItem_Selected(object sender, RoutedEventArgs e) { if (_ignoreTextValueChanged) return; _ignoreTextValueChanged = true; SelectAll(); _ignoreTextValueChanged = false; UpdateText(); } protected virtual void UpdateText() { if (_ignoreTextValueChanged) return; var newValue = string.Join(Delimiter, SelectedItems.Cast().Select(x => GetItemDisplayValue(x))); if (string.IsNullOrWhiteSpace(Text) || !Text.Equals(newValue)) { _ignoreTextValueChanged = true; if (_multiSelectComboBoxItem != null) _multiSelectComboBoxItem.SetCurrentValue(IsSelectedProperty, SelectedItems.Count == Items.Count); SetCurrentValue(TextProperty, newValue); _ignoreTextValueChanged = false; } } protected object GetItemDisplayValue(object item) { if (string.IsNullOrWhiteSpace(DisplayMemberPath)) { var property = item.GetType().GetProperty("Content"); if (property != null) return property.GetValue(item, null); } var nameParts = DisplayMemberPath.Split('.'); if (nameParts.Length == 1) { var property = item.GetType().GetProperty(DisplayMemberPath); if (property != null) return property.GetValue(item, null); } return item; } } }