基于WPF实现筛选下拉多选控件

Lala ·
更新时间:2024-09-20
· 71 次阅读

WPF 实现筛选下拉多选控件

框架使用.NET4 至 .NET6

Visual Studio 2022;

创建 MultiSelectionSearchComboBox 继承 Control .

模板中创建两个 ListBox

PART_Selector 用来显示所有 Item

PART_SearchSelector 用于记录筛选到的 Item

Item 继承 ListBoxItem 并将样式模板修改为 CheckBox

解决 Popup 中 IME 不跟随 TextBox 问题

private static extern IntPtr SetFocus(IntPtr hWnd);

当 TextBox 中 Text 发生改变时通过循环 Item 中的 GetProperty 获取特定 DisplayMemberPath 属性,判断是否包含输入的 SearchText值,如果包含则添加PART_SearchSelector 中,当 SelectionChanged 事件更改时将修改 PART_Selector 中的内容。

实现代码

1)创建 MultiSelectionSearchComboBox.cs 代码如下:

using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Interop; namespace WPFDevelopers.Controls {     [TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]     [TemplatePart(Name = "PART_Popup", Type = typeof(Popup))]     [TemplatePart(Name = "PART_Selector", Type = typeof(ListBox))]     [TemplatePart(Name = "PART_SelectAll", Type = typeof(CheckBox))]     [TemplatePart(Name = "PART_SearchSelector", Type = typeof(ListBox))]     public class MultiSelectionSearchComboBox : Control     {         private const string TextBoxTemplateName = "PART_TextBox";         private const string PopupTemplateName = "PART_Popup";         private const string ListBoxTemplateName = "PART_Selector";         private const string CheckBoxTemplateName = "PART_SelectAll";         private const string ListBoxTemplateNameSearch = "PART_SearchSelector";         public static readonly RoutedEvent ClosedEvent =             EventManager.RegisterRoutedEvent("Closed",                 RoutingStrategy.Bubble,                 typeof(RoutedEventHandler),                 typeof(MultiSelectionSearchComboBox));         public static readonly DependencyProperty DisplayMemberPathProperty =            DependencyProperty.Register("DisplayMemberPath",                typeof(string),                typeof(MultiSelectionSearchComboBox),                new PropertyMetadata(string.Empty));         public static readonly DependencyProperty SelectedValuePathProperty =            DependencyProperty.Register("SelectedValuePath",                typeof(string),                typeof(MultiSelectionSearchComboBox),                new PropertyMetadata(string.Empty));         public static readonly DependencyProperty TextProperty =             DependencyProperty.Register("Text",                 typeof(string),                 typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata(string.Empty));         public static readonly DependencyProperty ItemsSourceProperty =             DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata());         public static readonly DependencyProperty ItemsSourceSearchProperty =             DependencyProperty.Register("ItemsSourceSearch", typeof(IEnumerable), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata());         public static readonly DependencyProperty SelectAllContentProperty =             DependencyProperty.Register("SelectAllContent", typeof(object), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata("全选"));         public static readonly DependencyProperty IsSelectAllActiveProperty =             DependencyProperty.Register("IsSelectAllActive", typeof(bool), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata(false));         public static readonly DependencyProperty DelimiterProperty =             DependencyProperty.Register("Delimiter", typeof(string), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata(";"));         public static readonly DependencyProperty IsDropDownOpenProperty =             DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(MultiSelectionSearchComboBox),                 new PropertyMetadata(false, OnIsDropDownOpenChanged));         public static readonly DependencyProperty MaxDropDownHeightProperty =             DependencyProperty.Register("MaxDropDownHeight", typeof(double), typeof(MultiSelectionSearchComboBox),                 new UIPropertyMetadata(SystemParameters.PrimaryScreenHeight / 3.0, OnMaxDropDownHeightChanged));         public static readonly DependencyProperty SelectedItemsProperty =             DependencyProperty.Register("SelectedItems", typeof(IList), typeof(MultiSelectionSearchComboBox),                 new FrameworkPropertyMetadata(null,                     FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal,                     OnSelectedItemsChanged));         public static readonly DependencyProperty SearchWatermarkProperty =            DependencyProperty.Register("SearchWatermark",                typeof(string),                typeof(MultiSelectionSearchComboBox),                new PropertyMetadata(string.Empty));         private CheckBox _checkBox;         private ListBox _listBox;         private ListBox _listBoxSearch;         private Popup _popup;         private TextBox _textBox;         private List<object> selectedItems;         private List<object> selectedList;         private List<object> selectedSearchList;         private string theLastText;         static MultiSelectionSearchComboBox()         {             DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiSelectionSearchComboBox),                 new FrameworkPropertyMetadata(typeof(MultiSelectionSearchComboBox)));         }         public string Delimiter         {             get => (string)GetValue(DelimiterProperty);             set => SetValue(DelimiterProperty, value);         }         public string SelectedValuePath         {             get => (string)GetValue(SelectedValuePathProperty);             set => SetValue(SelectedValuePathProperty, value);         }         public string DisplayMemberPath         {             get => (string)GetValue(DisplayMemberPathProperty);             set => SetValue(DisplayMemberPathProperty, value);         }         public string Text         {             get => (string) GetValue(TextProperty);             set => SetValue(TextProperty, value);         }         public IEnumerable ItemsSource         {             get => (IEnumerable)GetValue(ItemsSourceProperty);             set => SetValue(ItemsSourceProperty, value);         }         public IEnumerable ItemsSourceSearch         {             get => (IEnumerable) GetValue(ItemsSourceSearchProperty);             set => SetValue(ItemsSourceSearchProperty, value);         }         public object SelectAllContent         {             get => GetValue(SelectAllContentProperty);             set => SetValue(SelectAllContentProperty, value);         }         public bool IsSelectAllActive         {             get => (bool) GetValue(IsSelectAllActiveProperty);             set => SetValue(IsSelectAllActiveProperty, value);         }         public bool IsDropDownOpen         {             get => (bool) GetValue(IsDropDownOpenProperty);             set => SetValue(IsDropDownOpenProperty, value);         }         public double MaxDropDownHeight         {             get => (double) GetValue(MaxDropDownHeightProperty);             set => SetValue(MaxDropDownHeightProperty, value);         }         public IList SelectedItems         {             get => (IList) GetValue(SelectedItemsProperty);             set => SetValue(SelectedItemsProperty, value);         }         public string SearchWatermark         {             get => (string)GetValue(SearchWatermarkProperty);             set => SetValue(SearchWatermarkProperty, value);         }         [DllImport("User32.dll")]         private static extern IntPtr SetFocus(IntPtr hWnd);         public event RoutedEventHandler Closed         {             add => AddHandler(ClosedEvent, value);             remove => RemoveHandler(ClosedEvent, value);         }         public override void OnApplyTemplate()         {             base.OnApplyTemplate();             selectedList = new List<object>();             selectedSearchList = new List<object>();             selectedItems = new List<object>();             _textBox = GetTemplateChild(TextBoxTemplateName) as TextBox;             _popup = GetTemplateChild(PopupTemplateName) as Popup;             if (_popup != null)                 _popup.GotFocus += _popup_GotFocus;             _listBox = GetTemplateChild(ListBoxTemplateName) as ListBox;             _checkBox = GetTemplateChild(CheckBoxTemplateName) as CheckBox;             _listBoxSearch = GetTemplateChild(ListBoxTemplateNameSearch) as ListBox;             if (_textBox != null)             {                 _textBox.TextChanged -= _textbox_TextChanged;                 _textBox.TextChanged += _textbox_TextChanged;             }             if (_checkBox != null)             {                 _checkBox.Checked -= _checkBox_Checked;                 _checkBox.Unchecked -= _checkBox_Unchecked;                 _checkBox.Checked += _checkBox_Checked;                 _checkBox.Unchecked += _checkBox_Unchecked;             }             if (_listBox != null)             {                 _listBox.IsVisibleChanged -= _listBox_IsVisibleChanged;                 _listBox.IsVisibleChanged += _listBox_IsVisibleChanged;                 _listBox.SelectionChanged -= _listBox_SelectionChanged;                 _listBox.SelectionChanged += _listBox_SelectionChanged;             }             if (_listBoxSearch != null)             {                 _listBoxSearch.IsVisibleChanged -= _listBoxSearch_IsVisibleChanged;                 _listBoxSearch.IsVisibleChanged += _listBoxSearch_IsVisibleChanged;                 _listBoxSearch.SelectionChanged -= _listBoxSearch_SelectionChanged;                 _listBoxSearch.SelectionChanged += _listBoxSearch_SelectionChanged;             }         }         private void _listBoxSearch_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)         {             if ((bool) e.NewValue)                 UpdateIsChecked(_listBoxSearch);         }         private void _listBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)         {             if ((bool) e.NewValue)             {                 foreach (var item in selectedSearchList)                     if (!_listBox.SelectedItems.Contains(item))                         _listBox.SelectedItems.Add(item);                 UpdateIsChecked(_listBox);             }         }         private void UpdateIsChecked(ListBox listBox)         {             _checkBox.Checked -= _checkBox_Checked;             if (listBox.Items.Count > 0 && listBox.Items.Count == listBox.SelectedItems.Count)             {                 if (_checkBox.IsChecked != true)                     _checkBox.IsChecked = true;             }             else             {                 if (listBox.SelectedItems.Count == 0)                     _checkBox.IsChecked = false;                 else                     _checkBox.IsChecked = null;             }             _checkBox.Checked += _checkBox_Checked;         }         private void _popup_GotFocus(object sender, RoutedEventArgs e)         {             var source = (HwndSource) PresentationSource.FromVisual(_popup.Child);             if (source != null)             {                 SetFocus(source.Handle);                 _textBox.Focus();             }         }         private void _checkBox_Unchecked(object sender, RoutedEventArgs e)         {             if (_listBoxSearch.Visibility == Visibility.Visible)                 _listBoxSearch.UnselectAll();             else                 _listBox.UnselectAll();         }         private void _checkBox_Checked(object sender, RoutedEventArgs e)         {             if (_listBoxSearch.Visibility == Visibility.Visible)                 _listBoxSearch.SelectAll();             else                 _listBox.SelectAll();         }         private void Combination()         {             var seletedName = new List<string>();             foreach (var item in _listBox.SelectedItems)             {                 var name = GetDisplayText(item);                 seletedName.Add(name);             }             foreach (var item in _listBoxSearch.SelectedItems)             {                 if (_listBox.SelectedItems.Contains(item))                     continue;                 var name = GetDisplayText(item);                 seletedName.Add(name);             }             Text = string.Join(Delimiter, seletedName.ToArray());         }         private void _listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)         {             if (e.RemovedItems.Count > 0)                 foreach (var item in e.RemovedItems)                     if (_checkBox.IsChecked == true)                     {                         _checkBox.Unchecked -= _checkBox_Unchecked;                         if (_listBox.Items.Count == 1)                             _checkBox.IsChecked = false;                         else                             _checkBox.IsChecked = null;                         _checkBox.Unchecked += _checkBox_Unchecked;                     }             if (e.AddedItems.Count > 0)                 SelectionChecked(_listBox);             Combination();             SelectedItems = _listBox.SelectedItems;         }         private void _listBoxSearch_SelectionChanged(object sender, SelectionChangedEventArgs e)         {             if (!_listBoxSearch.IsVisible) return;             if (e.RemovedItems.Count > 0)             {                 foreach (var item in e.RemovedItems)                     if (selectedSearchList.Contains(item))                         selectedSearchList.Remove(item);                 Combination();                 SelectionChecked(_listBoxSearch);             }             if (e.AddedItems.Count > 0)             {                 foreach (var item in e.AddedItems)                     if (!selectedSearchList.Contains(item))                         selectedSearchList.Add(item);                 Combination();                 SelectionChecked(_listBoxSearch);             }         }         private void SelectionChecked(ListBox listbox)         {             if (listbox.SelectedItems.Count > 0                 &&                 listbox.Items.Count == listbox.SelectedItems.Count)             {                 _checkBox.Checked -= _checkBox_Checked;                 _checkBox.IsChecked = true;                 _checkBox.Checked += _checkBox_Checked;             }             else             {                 _checkBox.Checked -= _checkBox_Checked;                 if (listbox.SelectedItems.Count > 0                     &&                      listbox.Items.Count == listbox.SelectedItems.Count)                 {                     if (_checkBox.IsChecked != true)                         _checkBox.IsChecked = true;                 }                 else                 {                     if (listbox.SelectedItems.Count == 0)                         _checkBox.IsChecked = false;                     else                         _checkBox.IsChecked = null;                 }                 _checkBox.Checked += _checkBox_Checked;             }         }         private string GetDisplayText(object dataItem, string path = null)         {             if (dataItem == null) return string.Empty;             return GetPropertyValue(dataItem);         }         private void _textbox_TextChanged(object sender, TextChangedEventArgs e)         {             if (string.IsNullOrWhiteSpace(theLastText)) theLastText = _textBox.Text;             SearchText(_textBox.Text);         }         private void SearchText(string _text)         {             var text = _text;             if (string.IsNullOrWhiteSpace(text))             {                 if (_listBoxSearch.Visibility != Visibility.Collapsed)                     _listBoxSearch.Visibility = Visibility.Collapsed;                 if (_listBox.Visibility != Visibility.Visible)                     _listBox.Visibility = Visibility.Visible;             }             else             {                 if(_listBoxSearch.Visibility != Visibility.Visible)                     _listBoxSearch.Visibility = Visibility.Visible;                 if(_listBox.Visibility != Visibility.Collapsed)                     _listBox.Visibility = Visibility.Collapsed;                 var listSearch = new List<object>();                 foreach (var item in _listBox.Items)                 {                     var str = GetPropertyValue(item);                     if (!string.IsNullOrWhiteSpace(str))                         if (str.Contains(text.ToUpperInvariant()))                             listSearch.Add(item);                 }                 foreach (var item in selectedList)                     if (!listSearch.Contains(item))                         listSearch.Add(item);                 var lastItem = ItemsSourceSearch;                 ItemsSourceSearch = listSearch;                 SelectionChecked(_listBoxSearch);                 selectedItems.Clear();                 foreach (var item in _listBoxSearch.Items)                     if (_listBox.SelectedItems.Contains(item))                         if (!_listBoxSearch.SelectedItems.Contains(item))                             _listBoxSearch.SelectedItems.Add(item);             }         }         private string GetPropertyValue(object item)         {             var result = string.Empty;             var nameParts = DisplayMemberPath.Split('.');             if (nameParts.Length == 1)             {                 var property = item.GetType().GetProperty(DisplayMemberPath);                 if (property != null)                     return (property.GetValue(item, null) ?? string.Empty).ToString();             }             return result.ToUpperInvariant();         }         private static void OnIsDropDownOpenChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)         {             var multiSelectionSearchComboBox = o as MultiSelectionSearchComboBox;             if (multiSelectionSearchComboBox != null)                 multiSelectionSearchComboBox.OnIsOpenChanged((bool) e.OldValue, (bool) e.NewValue);         }         protected virtual void OnIsOpenChanged(bool oldValue, bool newValue)         {             if (!newValue)                 RaiseRoutedEvent(ClosedEvent);         }         private void RaiseRoutedEvent(RoutedEvent routedEvent)         {             var args = new RoutedEventArgs(routedEvent, this);             RaiseEvent(args);         }         private static void OnMaxDropDownHeightChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)         {             var comboBox = o as MultiSelectionSearchComboBox;             if (comboBox != null)                 comboBox.OnMaxDropDownHeightChanged((double) e.OldValue, (double) e.NewValue);         }         protected virtual void OnMaxDropDownHeightChanged(double oldValue, double newValue)         {         }         private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)         {             var mltiSelectionSearchComboBox = d as MultiSelectionSearchComboBox;             if (e.NewValue != null)             {                 var collection = e.NewValue as IList;                 if (collection.Count <= 0) return;                 if (e.OldValue != null && mltiSelectionSearchComboBox._listBox != null)                 {                     mltiSelectionSearchComboBox._listBox.SelectionChanged -=                         mltiSelectionSearchComboBox._listBox_SelectionChanged;                     mltiSelectionSearchComboBox._listBox.SelectedItems.Clear();                 }                 foreach (var item in collection)                 {                     var name = mltiSelectionSearchComboBox.GetPropertyValue(item);                     var model = mltiSelectionSearchComboBox._listBox.ItemsSource.OfType<object>().FirstOrDefault(h =>                         mltiSelectionSearchComboBox.GetPropertyValue(h).ToUpperInvariant()                             .Equals(name));                     if (model != null && !mltiSelectionSearchComboBox._listBox.SelectedItems.Contains(item))                         mltiSelectionSearchComboBox._listBox.SelectedItems.Add(model);                     if (e.OldValue != null && mltiSelectionSearchComboBox._listBox != null)                         mltiSelectionSearchComboBox._listBox.SelectionChanged +=                             mltiSelectionSearchComboBox._listBox_SelectionChanged;                     mltiSelectionSearchComboBox.Combination();                 }             }         }     } }

2)创建 MultiSelectionListBox.xaml 代码如下:

using System.Windows; using System.Windows.Controls; namespace WPFDevelopers.Controls {     public class MultiSelectionListBox:ListBox     {         protected override bool IsItemItsOwnContainerOverride(object item)         {             return item is MultiSelectComboBoxItem;         }         protected override DependencyObject GetContainerForItemOverride()         {             return new MultiSelectComboBoxItem();         }     } }

3)创建 MultiSelectionSearchComboBox.xaml 代码如下:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                     xmlns:controls="clr-namespace:WPFDevelopers.Controls"                     xmlns:helpers="clr-namespace:WPFDevelopers.Helpers">     <ResourceDictionary.MergedDictionaries>         <ResourceDictionary Source="Basic/ControlBasic.xaml"/>         <ResourceDictionary Source="MultiSelectionComboBox.xaml"/>     </ResourceDictionary.MergedDictionaries>     <Style TargetType="{x:Type controls:MultiSelectionSearchComboBox}">   <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />   <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />   <Setter Property="ScrollViewer.CanContentScroll" Value="True" />   <Setter Property="MinWidth" Value="120" />   <Setter Property="MinHeight" Value="{StaticResource MinHeight}" />         <Setter Property="Height" Value="{StaticResource MinHeight}" />   <Setter Property="HorizontalContentAlignment" Value="Left" />   <Setter Property="VerticalContentAlignment" Value="Center" />         <Setter Property="BorderBrush" Value="{DynamicResource BaseSolidColorBrush}"/>         <Setter Property="BorderThickness" Value="1"/>   <Setter Property="Background" Value="{DynamicResource BackgroundSolidColorBrush}"/>   <Setter Property="Padding" Value="14.5,3,30,3"/>         <Setter Property="Template">    <Setter.Value>                 <ControlTemplate TargetType="{x:Type controls:MultiSelectionSearchComboBox}">      <ControlTemplate.Resources>       <Storyboard x:Key="OpenStoryboard">        <DoubleAnimation Storyboard.TargetName="PART_DropDown"              Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)"              To="1" Duration="00:00:.2"              EasingFunction="{StaticResource ExponentialEaseOut}"/>       </Storyboard>       <Storyboard x:Key="CloseStoryboard">        <DoubleAnimation Storyboard.TargetName="PART_DropDown"              Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)"              To="0" Duration="00:00:.2"              EasingFunction="{StaticResource ExponentialEaseOut}"/>       </Storyboard>      </ControlTemplate.Resources>                     <controls:SmallPanel SnapsToDevicePixels="True">       <Border Name="PART_Border"         Background="{TemplateBinding Background}"         BorderBrush="{TemplateBinding BorderBrush}"         BorderThickness="{TemplateBinding BorderThickness}"         SnapsToDevicePixels="True"         CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}" />       <ToggleButton x:Name="PART_ToggleButton"            Template="{StaticResource ComboBoxToggleButton}"            Style="{x:Null}"            Focusable="False"            ClickMode="Release"            IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>       <TextBox Name="PART_EditableTextBox"          Template="{StaticResource ComboBoxTextBox}"          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"          Margin="{TemplateBinding Padding}"          Focusable="True"                                  Foreground="{DynamicResource PrimaryTextSolidColorBrush}"          Text="{Binding Text,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"          Background="{TemplateBinding Background}"          SelectionBrush="{DynamicResource WindowBorderBrushSolidColorBrush}"          IsReadOnly="True" Style="{x:Null}" />                         <TextBlock x:Name="PART_Watermark"                                    Text="{Binding Path=(helpers:ElementHelper.Watermark),RelativeSource={RelativeSource TemplatedParent}}"                                    Foreground="{DynamicResource RegularTextSolidColorBrush}"                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"                                    FontSize="{StaticResource NormalFontSize}"                                    Margin="{TemplateBinding Padding}"                                     Background="Transparent"                                    TextTrimming="CharacterEllipsis"                                    IsHitTestVisible="False"                                    Padding="1,0"                                     Visibility="Collapsed"/>                         <Popup x:Name="PART_Popup"         AllowsTransparency="True"         PlacementTarget="{Binding ElementName=PART_ToggleButton}"         IsOpen="{Binding IsDropDownOpen,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"         Placement="Bottom" StaysOpen="False">                             <controls:SmallPanel x:Name="PART_DropDown"           MinWidth="{TemplateBinding FrameworkElement.ActualWidth}"         Margin="24,2,24,24"         MaxHeight="{TemplateBinding MaxDropDownHeight}"         RenderTransformOrigin=".5,0"         SnapsToDevicePixels="True">                                 <controls:SmallPanel.RenderTransform>          <ScaleTransform ScaleY="0"/>         </controls:SmallPanel.RenderTransform>         <Border          Name="PART_DropDownBorder"          Background="{TemplateBinding Background}"          BorderBrush="{TemplateBinding BorderBrush}"          BorderThickness="{TemplateBinding BorderThickness}"          SnapsToDevicePixels="True"                                  CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}"          UseLayoutRounding="True"          Effect="{StaticResource PopupShadowDepth}"/>         <Grid ClipToBounds="False"            Margin="0,8" >          <Grid.RowDefinitions>           <RowDefinition Height="Auto"/>                                         <RowDefinition Height="Auto"/>           <RowDefinition/>          </Grid.RowDefinitions>                                     <TextBox x:Name="PART_TextBox"                                              Margin="6,0"                                              helpers:ElementHelper.Watermark="{Binding SearchWatermark,RelativeSource={RelativeSource TemplatedParent}}"/>                                     <CheckBox x:Name="PART_SelectAll"                                               Grid.Row="1"                                               Margin="5,4"                                               Visibility="{TemplateBinding IsSelectAllActive,Converter={StaticResource bool2VisibilityConverter}}"                                               Content="{TemplateBinding SelectAllContent}"/>                                     <controls:MultiSelectListBox x:Name="PART_Selector"                                              Grid.Row="2"                                              BorderThickness="1,0,1,0"                                              DisplayMemberPath="{TemplateBinding DisplayMemberPath}"                                              SelectedValuePath="{TemplateBinding SelectedValuePath}"                                              MinHeight="{TemplateBinding MinHeight}"             ItemsSource="{TemplateBinding ItemsSource}"                                              SelectionMode="Multiple"                                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"                                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"                                              ItemContainerStyle="{StaticResource DefaultMultiSelectComboBoxItem}"                                              ScrollViewer.HorizontalScrollBarVisibility="{Binding ScrollViewer.HorizontalScrollBarVisibility, RelativeSource={RelativeSource TemplatedParent}}"                                              ScrollViewer.CanContentScroll="{Binding ScrollViewer.CanContentScroll, RelativeSource={RelativeSource TemplatedParent}}"                                              BorderBrush="{TemplateBinding BorderBrush}">                                     </controls:MultiSelectListBox>                                     <controls:MultiSelectListBox x:Name="PART_SearchSelector"                                              Grid.Row="2"                                              BorderThickness="1,0,1,0"                                              BorderBrush="{TemplateBinding BorderBrush}"                                              DisplayMemberPath="{TemplateBinding DisplayMemberPath}"                                              SelectedValuePath="{TemplateBinding SelectedValuePath}"                                              MinHeight="{TemplateBinding MinHeight}"             ItemsSource="{TemplateBinding ItemsSourceSearch}"                                              SelectionMode="Multiple"                                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"                                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"                                              ItemContainerStyle="{StaticResource DefaultMultiSelectComboBoxItem}"                                              ScrollViewer.HorizontalScrollBarVisibility="{Binding ScrollViewer.HorizontalScrollBarVisibility, RelativeSource={RelativeSource TemplatedParent}}"                                              ScrollViewer.CanContentScroll="{Binding ScrollViewer.CanContentScroll, RelativeSource={RelativeSource TemplatedParent}}"                                              Visibility="Collapsed">                                     </controls:MultiSelectListBox>                                 </Grid>        </controls:SmallPanel>       </Popup>      </controls:SmallPanel>      <ControlTemplate.Triggers>       <Trigger SourceName="PART_ToggleButton" Property="IsChecked" Value="True">        <Trigger.EnterActions>         <BeginStoryboard x:Name="BeginStoryboardOpenStoryboard" Storyboard="{StaticResource OpenStoryboard}" />        </Trigger.EnterActions>        <Trigger.ExitActions>         <StopStoryboard BeginStoryboardName="BeginStoryboardOpenStoryboard" />        </Trigger.ExitActions>       </Trigger>       <Trigger SourceName="PART_ToggleButton" Property="IsChecked" Value="False">        <Trigger.EnterActions>         <BeginStoryboard x:Name="BeginStoryboardCloseStoryboard" Storyboard="{StaticResource CloseStoryboard}" />        </Trigger.EnterActions>        <Trigger.ExitActions>         <StopStoryboard BeginStoryboardName="BeginStoryboardCloseStoryboard" />        </Trigger.ExitActions>       </Trigger>       <Trigger Property="IsMouseOver" Value="True">                             <Setter Property="BorderBrush" TargetName="PART_Border" Value="{DynamicResource PrimaryNormalSolidColorBrush}"/>       </Trigger>       <Trigger SourceName="PART_Popup" Property="AllowsTransparency" Value="True">        <Setter TargetName="PART_DropDownBorder"  Property="Margin" Value="0,2,0,0" />       </Trigger>                         <Trigger Property="Text" Value="">                             <Setter Property="Visibility" TargetName="PART_Watermark" Value="Visible"/>                         </Trigger>                         <Trigger Property="Text" Value="{x:Null}">                             <Setter Property="Visibility" TargetName="PART_Watermark" Value="Visible"/>                         </Trigger>      </ControlTemplate.Triggers>     </ControlTemplate>    </Setter.Value>   </Setter>  </Style> </ResourceDictionary>

4)创建 MultiSelectSearchComboBoxExample.xaml 代码如下:

 <Grid>             <Grid.RowDefinitions>                 <RowDefinition Height="Auto"/>                 <RowDefinition/>             </Grid.RowDefinitions>             <Button Content="获取选中"                      VerticalAlignment="Bottom"                     HorizontalAlignment="Center"                     Click="Button_Click"                     Margin="0,20,0,0"                     Style="{StaticResource SuccessPrimaryButton}"/>             <UniformGrid Columns="2" Rows="2" Grid.Row="1">                 <wd:MultiSelectionSearchComboBox                 VerticalContentAlignment="Center"                  HorizontalAlignment="Center"                     ItemsSource="{Binding Drawings}"                  DisplayMemberPath="Number"                 SelectedValuePath="Index"                 Width="200" Delimiter=","                 IsSelectAllActive="True">                     <wd:MultiSelectionSearchComboBox.DataContext>                         <vm:DrawingExampleVM/>                     </wd:MultiSelectionSearchComboBox.DataContext>                 </wd:MultiSelectionSearchComboBox>                 <wd:MultiSelectionSearchComboBox                     Name="MyMultiSelectionSearchComboBox2"                 VerticalContentAlignment="Center"                  HorizontalAlignment="Center"                 ItemsSource="{Binding Drawings}"                  DisplayMemberPath="Number"                 SelectedValuePath="Index"                 Width="200" Delimiter="^"                 IsSelectAllActive="True"                 wd:ElementHelper.Watermark="MultiSelectionSearchComboBox"                 SearchWatermark="请输入搜索内容">                     <wd:MultiSelectionSearchComboBox.DataContext>                         <vm:DrawingExampleVM/>                     </wd:MultiSelectionSearchComboBox.DataContext>                 </wd:MultiSelectionSearchComboBox>             </UniformGrid>         </Grid>

5)创建 MultiSelectSearchComboBoxExample.xaml.cs 代码如下:

using System.Windows; using System.Windows.Controls; namespace WPFDevelopers.Samples.ExampleViews {     /// <summary>     /// MultiSelectComboBoxExample.xaml 的交互逻辑     /// </summary>     public partial class MultiSelectSearchComboBoxExample : UserControl     {         public MultiSelectSearchComboBoxExample()         {             InitializeComponent();         }         private void Button_Click(object sender, System.Windows.RoutedEventArgs e)         {             WPFDevelopers.Controls.MessageBox.Show($"{MyMultiSelectionSearchComboBox2.Text} \r\n总共选中:{MyMultiSelectionSearchComboBox2.SelectedItems.Count} 条","选中内容",MessageBoxButton.OK,MessageBoxImage.Information);               }     } }

效果图

以上就是基于WPF实现筛选下拉多选控件的详细内容,更多关于WPF筛选下拉多选控件的资料请关注软件开发网其它相关文章!



wpf

需要 登录 后方可回复, 如果你还没有账号请 注册新账号