183 lines
6.3 KiB
C#
183 lines
6.3 KiB
C#
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.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<object>().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;
|
|
}
|
|
}
|
|
}
|