基于WPF实现筛选下拉多选控件
作者:WPF开发者
这篇文章主要为大家详细介绍了如何基于WPF实现简单的筛选下拉多选控件,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下
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筛选下拉多选控件的资料请关注脚本之家其它相关文章!