基于WPF实现多选下拉控件的示例代码

WPF 实现多选下拉控件

框架使用.NET40

Visual Studio 2022;

创建控件 MultiSelectComboBox 继承 ListBox 。

  • 依赖属性 IsSelectAllActive 是否支持显示全选,默认 false 。
  • 依赖属性 SelectAllContent 全选控件的 Content,默认显示 全选 。
  • 依赖属性 Delimiter 分隔符,默认显示 ; 。
  • 依赖属性 Text 显示选择的所有 Item 。
  • 其他与ComboBox 依赖属性一致。

基于WPF实现多选下拉控件的示例代码_第1张图片

实现代码

1) MultiSelectComboBox.xaml 代码如下:

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 WPFDevelopers.Controls
{
    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;
        }
    }
}


2) MultiSelectComboBoxItem.cs 代码如下:

using System.Windows.Controls;

namespace WPFDevelopers.Controls
{
    public class MultiSelectComboBoxItem : ListBoxItem
    {
    }
}

3) MultiSelectComboBox.xaml 代码如下:


    
    
        
    
  
 
  
  
  
  
  
  
  
  
  
  
  
  
   
    

     
      

       
      
     
     
      
       
      
     
    
   
  
 

 
  
  
  
  
  
  
        
  
  
  
        
        
  
  
  
   
                
     
      
       
      
      
       
      
     
                    
      


      
      
      
      
                            
                                
         
        
        
        
         
          
          
         
         
         
          
         
        
       
      
     
     
      
       
        
       
       
        
       
      
      
       
        
       
       
        
       
      
      
                            
      
      
       
      
     
    
   
  
 

4) MultiSelectComboBoxExample.xaml 代码如下:


    
        
    
    
        
            
                Option 1
                Option 2
                Option 3
                Option 4
                Option 5
            
            

            
        
        
            
            
        
    

效果图

基于WPF实现多选下拉控件的示例代码_第2张图片

以上就是基于WPF实现多选下拉控件的示例代码的详细内容,更多关于WPF多选下拉控件的资料请关注脚本之家其它相关文章!

你可能感兴趣的:(基于WPF实现多选下拉控件的示例代码)