WPF 实现筛选下拉多选控件
框架使用.NET4 至 .NET6;Visual Studio 2022;
创建 MultiSelectionSearchComboBox 继承 Control .
模板中创建两个 ListBox
PART_Selector 用来显示所有 ItemPART_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 代码如下:
usingSystem;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Runtime.InteropServices;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Controls.Primitives;
usingSystem.Windows.Interop;
namespaceWPFDevelopers.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))]
publicclassMultiSelectionSearchComboBox:Control
{
privateconststringTextBoxTemplateName="PART_TextBox";
privateconststringPopupTemplateName="PART_Popup";
privateconststringListBoxTemplateName="PART_Selector";
privateconststringCheckBoxTemplateName="PART_SelectAll";
privateconststringListBoxTemplateNameSearch="PART_SearchSelector";
publicstaticreadonlyRoutedEventClosedEvent=
EventManager.RegisterRoutedEvent("Closed",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(MultiSelectionSearchComboBox));
publicstaticreadonlyDependencyPropertyDisplayMemberPathProperty=
DependencyProperty.Register("DisplayMemberPath",
typeof(string),
typeof(MultiSelectionSearchComboBox),
newPropertyMetadata(string.Empty));
publicstaticreadonlyDependencyPropertySelectedValuePathProperty=
DependencyProperty.Register("SelectedValuePath",
typeof(string),
typeof(MultiSelectionSearchComboBox),
newPropertyMetadata(string.Empty));
publicstaticreadonlyDependencyPropertyTextProperty=
DependencyProperty.Register("Text",
typeof(string),
typeof(MultiSelectionSearchComboBox),
newPropertyMetadata(string.Empty));
publicstaticreadonlyDependencyPropertyItemsSourceProperty=
DependencyProperty.Register("ItemsSource",typeof(IEnumerable),typeof(MultiSelectionSearchComboBox),
newPropertyMetadata());
publicstaticreadonlyDependencyPropertyItemsSourceSearchProperty=
DependencyProperty.Register("ItemsSourceSearch",typeof(IEnumerable),typeof(MultiSelectionSearchComboBox),
newPropertyMetadata());
publicstaticreadonlyDependencyPropertySelectAllContentProperty=
DependencyProperty.Register("SelectAllContent",typeof(object),typeof(MultiSelectionSearchComboBox),
newPropertyMetadata("全选"));
publicstaticreadonlyDependencyPropertyIsSelectAllActiveProperty=
DependencyProperty.Register("IsSelectAllActive",typeof(bool),typeof(MultiSelectionSearchComboBox),
newPropertyMetadata(false));
publicstaticreadonlyDependencyPropertyDelimiterProperty=
DependencyProperty.Register("Delimiter",typeof(string),typeof(MultiSelectionSearchComboBox),
newPropertyMetadata(";"));
publicstaticreadonlyDependencyPropertyIsDropDownOpenProperty=
DependencyProperty.Register("IsDropDownOpen",typeof(bool),typeof(MultiSelectionSearchComboBox),
newPropertyMetadata(false,OnIsDropDownOpenChanged));
publicstaticreadonlyDependencyPropertyMaxDropDownHeightProperty=
DependencyProperty.Register("MaxDropDownHeight",typeof(double),typeof(MultiSelectionSearchComboBox),
newUIPropertyMetadata(SystemParameters.PrimaryScreenHeight/3.0,OnMaxDropDownHeightChanged));
publicstaticreadonlyDependencyPropertySelectedItemsProperty=
DependencyProperty.Register("SelectedItems",typeof(IList),typeof(MultiSelectionSearchComboBox),
newFrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault|FrameworkPropertyMetadataOptions.Journal,
OnSelectedItemsChanged));
publicstaticreadonlyDependencyPropertySearchWatermarkProperty=
DependencyProperty.Register("SearchWatermark",
typeof(string),
typeof(MultiSelectionSearchComboBox),
newPropertyMetadata(string.Empty));
privateCheckBox_checkBox;
privateListBox_listBox;
privateListBox_listBoxSearch;
privatePopup_popup;
privateTextBox_textBox;
privateList<object>selectedItems;
privateList<object>selectedList;
privateList<object>selectedSearchList;
privatestringtheLastText;
staticMultiSelectionSearchComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiSelectionSearchComboBox),
newFrameworkPropertyMetadata(typeof(MultiSelectionSearchComboBox)));
}
publicstringDelimiter
{
get=>(string)GetValue(DelimiterProperty);
set=>SetValue(DelimiterProperty,value);
}
publicstringSelectedValuePath
{
get=>(string)GetValue(SelectedValuePathProperty);
set=>SetValue(SelectedValuePathProperty,value);
}
publicstringDisplayMemberPath
{
get=>(string)GetValue(DisplayMemberPathProperty);
set=>SetValue(DisplayMemberPathProperty,value);
}
publicstringText
{
get=>(string)GetValue(TextProperty);
set=>SetValue(TextProperty,value);
}
publicIEnumerableItemsSource
{
get=>(IEnumerable)GetValue(ItemsSourceProperty);
set=>SetValue(ItemsSourceProperty,value);
}
publicIEnumerableItemsSourceSearch
{
get=>(IEnumerable)GetValue(ItemsSourceSearchProperty);
set=>SetValue(ItemsSourceSearchProperty,value);
}
publicobjectSelectAllContent
{
get=>GetValue(SelectAllContentProperty);
set=>SetValue(SelectAllContentProperty,value);
}
publicboolIsSelectAllActive
{
get=>(bool)GetValue(IsSelectAllActiveProperty);
set=>SetValue(IsSelectAllActiveProperty,value);
}
publicboolIsDropDownOpen
{
get=>(bool)GetValue(IsDropDownOpenProperty);
set=>SetValue(IsDropDownOpenProperty,value);
}
publicdoubleMaxDropDownHeight
{
get=>(double)GetValue(MaxDropDownHeightProperty);
set=>SetValue(MaxDropDownHeightProperty,value);
}
publicIListSelectedItems
{
get=>(IList)GetValue(SelectedItemsProperty);
set=>SetValue(SelectedItemsProperty,value);
}
publicstringSearchWatermark
{
get=>(string)GetValue(SearchWatermarkProperty);
set=>SetValue(SearchWatermarkProperty,value);
}
[DllImport("User32.dll")]
privatestaticexternIntPtrSetFocus(IntPtrhWnd);
publiceventRoutedEventHandlerClosed
{
add=>AddHandler(ClosedEvent,value);
remove=>RemoveHandler(ClosedEvent,value);
}
publicoverridevoidOnApplyTemplate()
{
base.OnApplyTemplate();
selectedList=newList<object>();
selectedSearcList=newList<object>();
selectedItems=newList<object>();
_textBox=GetTemplateChild(TextBoxTemplateName)asTextBox;
_popup=GetTemplateChild(PopupTemplateName)asPopup;
if(_popup!=null)
_popup.GotFocus+=_popup_GotFocus;
_listBox=GetTemplateChild(ListBoxTemplateName)asListBox;
_checkBox=GetTemplateChild(CheckBoxTemplateName)asCheckBox;
_listBoxSearch=GetTemplateChild(ListBoxTemplateNameSearch)asListBox;
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;
}
}
privatevoid_listBoxSearch_IsVisibleChanged(objectsender,DependencyPropertyChangedEventArgse)
{
if((bool)e.NewValue)
UpdateIsChecked(_listBoxSearch);
}
privatevoid_listBox_IsVisibleChanged(objectsender,DependencyPropertyChangedEventArgse)
{
if((bool)e.NewValue)
{
foreach(variteminselectedSearchList)
if(!_listBox.SelectedItems.Contains(item))
_listBox.SelectedItems.Add(item);
UpdateIsChecked(_listBox);
}
}
privatevoidUpdateIsChecked(ListBoxlistBox)
{
_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;
}
privatevoid_popup_GotFocus(objectsender,RoutedEventArgse)
{
varsource=(HwndSource)PresentationSource.FromVisual(_popup.Child);
if(source!=null)
{
SetFocus(source.Handle);
_textBox.Focus();
}
}
privatevoid_checkBox_Unchecked(objectsender,RoutedEventArgse)
{
if(_listBoxSearch.Visibility==Visibility.Visible)
_listBoxSearch.UnselectAll();
else
_listBox.UnselectAll();
}
privatevoid_checkBox_Checked(objectsender,RoutedEventArgse)
{
if(_listBoxSearch.Visibility==Visibility.Visible)
_listBoxSearch.SelectAll();
else
_listBox.SelectAll();
}
privatevoidCombination()
{
varseletedName=newList<string>();
foreach(varitemin_listBox.SelectedItems)
{
varname=GetDisplayText(item);
seletedName.Add(name);
}
foreach(varitemin_listBoxSearch.SelectedItems)
{
if(_listBox.SelectedItems.Contains(item))
continue;
varname=GetDisplayText(item);
seletedName.Add(name);
}
Text=string.Join(Delimiter,seletedName.ToArray());
}
privatevoid_listBox_SelectionChanged(objectsender,SelectionChangedEventArgse)
{
if(e.RemovedItems.Count>0)
foreach(varitemine.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;
}
privatevoid_listBoxSearch_SelectionChanged(objectsender,SelectionChangedEventArgse)
{
if(!_listBoxSearch.IsVisible)return;
if(e.RemovedItems.Count>0)
{
foreach(varitemine.RemovedItems)
if(selectedSearchList.Contains(item))
selectedSearchList.Remove(item);
Combination();
SelectionChecked(_listBoxSearch);
}
if(e.AddedItems.Count>0)
{
foreach(varitemine.AddedItems)
if(!selectedSearchList.Contains(item))
selectedSearchList.Add(item);
Combination();
SelectionChecked(_listBoxSearch);
}
}
privatevoidSelectionChecked(ListBoxlistbox)
{
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;
}
}
privatestringGetDisplayText(objectdataItem,stringpath=null)
{
if(dataItem==null)returnstring.Empty;
returnGetPropertyValue(dataItem);
}
privatevoid_textbox_TextChanged(objectsender,TextChangedEventArgse)
{
if(string.IsNullOrWhiteSpace(theLastText))theLastText=_textBox.Text;
SearchText(_textBox.Text);
}
privatevoidSearchText(string_text)
{
vartext=_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;
varlistSearch=newList<object>();
foreach(varitemin_listBox.Items)
{
varstr=GetPropertyValue(item);
if(!string.IsNullOrWhiteSpace(str))
if(str.Contains(text.ToUpperInvariant()))
listSearch.Add(item);
}
foreach(variteminselectedList)
if(!listSearch.Contains(item))
listSearch.Add(item);
varlastItem=ItemsSourceSearch;
ItemsSourceSearch=listSearch;
SelectionChecked(_listBoxSearch);
selectedItems.Clear();
foreach(varitemin_listBoxSearch.Items)
if(_listBox.SelectedItems.Contains(item))
if(!_listBoxSearch.SelectedItems.Contains(item))
_listBoxSearch.SelectedItems.Add(item);
}
}
privatestringGetPropertyValue(objectitem)
{
varresult=string.Empty;
varnameParts=DisplayMemberPath.Split('.');
if(nameParts.Length==1)
{
varproperty=item.GetType().GetProperty(DisplayMemberPath);
if(property!=null)
return(property.GetValue(item,null)??string.Empty).ToString();
}
returnresult.ToUpperInvariant();
}
privatestaticvoidOnIsDropDownOpenChanged(DependencyObjecto,DependencyPropertyChangedEventArgse)
{
varmultiSelectionSearchComboBox=oasMultiSelectionSearchComboBox;
if(multiSelectionSearchComboBox!=null)
multiSelectionSearchComboBox.OnIsOpenChanged((bool)e.OldValue,(bool)e.NewValue);
}
protectedvirtualvoidOnIsOpenChanged(boololdValue,boolnewValue)
{
if(!newValue)
RaiseRoutedEvent(ClosedEvent);
}
privatevoidRaiseRoutedEvent(RoutedEventroutedEvent)
{
varargs=newRoutedEventArgs(routedEvent,this);
RaiseEvent(args);
}
privatestaticvoidOnMaxDropDownHeightChanged(DependencyObjecto,DependencyPropertyChangedEventArgse)
{
varcomboBox=oasMultiSelectionSearchComboBox;
if(comboBox!=null)
comboBox.OnMaxDropDownHeightChanged((double)e.OldValue,(double)e.NewValue);
}
protectedvirtualvoidOnMaxDropDownHeightChanged(doubleoldValue,doublenewValue)
{
}
privatestaticvoidOnSelectedItemsChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)
{
varmltiSelectionSearchComboBox=dasMultiSelectionSearchComboBox;
if(e.NewValue!=null)
{
varcollection=e.NewValueasIList;
if(collection.Count<=0)return;
if(e.OldValue!=null&&mltiSelectionSearchComboBox._listBox!=null)
{
mltiSelectionSearchComboBox._listBox.SelectionChanged-=
mltiSelectionSearchComboBox._listBox_SelectionChanged;
mltiSelectionSearchComboBox._listBox.SelectedItems.Clear();
}
foreach(varitemincollection)
{
varname=mltiSelectionSearchComboBox.GetPropertyValue(item);
varmodel=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 代码如下:
usingSystem.Windows;
usingSystem.Windows.Controls;
namespaceWPFDevelopers.Controls
{
publicclassMultiSelectionListBox:ListBox
{
protectedoverrideboolIsItemItsOwnContainerOverride(objectitem)
{
returnitemisMultiSelectComboBoxItem;
}
protectedoverrideDependencyObjectGetContainerForItemOverride()
{
returnnewMultiSelectComboBoxItem();
}
}
}
3)创建 MultiSelectionSearchComboBox.xaml 代码如下:
<ResourceDictionaryxmlns="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>
<ResourceDictionarySource="Basic/ControlBasic.xaml"/>
<ResourceDictionarySource="MultiSelectionComboBox.xaml"/>
</ResourceDictionary.MergedDictionaries>
<StyleTargetType="{x:Typecontrols:MultiSelectionSearchComboBox}">
<SetterProperty="ScrollViewer.HorizontalScrollBarVisibility"Value="Auto"/>
<SetterProperty="ScrollViewer.VerticalScrollBarVisibility"Value="Auto"/>
<SetterProperty="ScrollViewer.CanContentScroll"Value="True"/>
<SetterProperty="MinWidth"Value="120"/>
<SetterProperty="MinHeight"Value="{StaticResourceMinHeight}"/>
<SetterProperty="Height"Value="{StaticResourceMinHeight}"/>
<SetterProperty="HorizontalContentAlignment"Value="Left"/>
<SetterProperty="VerticalContentAlignment"Value="Center"/>
<SetterProperty="BorderBrush"Value="{DynamicResourceBaseSolidColorBrush}"/>
<SetterProperty="BorderThickness"Value="1"/>
<SetterProperty="Background"Value="{DynamicResourceBackgroundSolidColorBrush}"/>
<SetterProperty="Padding"Value="14.5,3,30,3"/>
<SetterProperty="Template">
<Setter.Value>
<ControlTemplateTargetType="{x:Typecontrols:MultiSelectionSearchComboBox}">
<ControlTemplate.Resources>
<Storyboardx:Key="OpenStoryboard">
<DoubleAnimationStoryboard.TargetName="PART_DropDown"
Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)"
To="1"Duration="00:00:.2"
EasingFunction="{StaticResourceExponentialEaseOut}"/>
</Storyboard>
<Storyboardx:Key="CloseStoryboard">
<DoubleAnimationStoryboard.TargetName="PART_DropDown"
Storyboard.TargetProperty="(Grid.RenderTransform).(ScaleTransform.ScaleY)"
To="0"Duration="00:00:.2"
EasingFunction="{StaticResourceExponentialEaseOut}"/>
</Storyboard>
</ControlTemplate.Resources>
<control:SmallPanelSnapsToDevicePixels="True">
<BorderName="PART_Border"
Background="{TemplateBindingBackground}"
BorderBrush="{TemplateBindingBorderBrush}"
BorderThickness="{TemplateBindingBorderThickness}"
SnapsToDevicePixels="True"
CornerRadius="{BindingPath=(helpers:ElementHelper.CornerRadius),RelativeSource={RelativeSourceTemplatedParent}}"/>
<ToggleButtonx:Name="PART_ToggleButton"
Template="{StaticResourceComboBoxToggleButton}"
Style="{x:Null}"
Focusable="False"
ClickMode="Release"
IsChecked="{BindingIsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSourceTemplatedParent}}"/>
<TextBoxName="PART_EditableTextBox"
Template="{StaticResourceComboBoxTextBox}"
HorizontalAlignment="{TemplateBindingHorizontalContentAlignment}"
VerticalAlignment="{TemplateBindingVerticalContentAlignment}"
Margin="{TemplateBindingPadding}"
Focusable="True"
Foreground="{DynamicResourcePrimaryTextSolidColorBrush}"
Text="{BindingText,RelativeSource={RelativeSourceTemplatedParent},Mode=TwoWay}"
Background="{TemplateBindingBackground}"
SelectionBrush="{DynamicResourceWindowBorderBrushSolidColorBrush}"
IsReadOnly="True"Style="{x:Null}"/>
<TextBlockx:Name="PART_Watermark"
Text="{BindingPath=(helpers:ElementHelper.Watermark),RelativeSource={RelativeSourceTemplatedParent}}"
Foreground="{DynamicResourceRegularTextSolidColorBrush}"
HorizontalAlignment="{TemplateBindingHorizontalContentAlignment}"
VerticalAlignment="{TemplateBindingVerticalContentAlignment}"
FontSize="{StaticResourceNormalFontSize}"
Margin="{TemplateBindingPadding}"
Background="Transparent"
TextTrimming="CharacterEllipsis"
IsHitTestVisible="False"
Padding="1,0"
Visibility="Collapsed"/>
<Popupx:Name="PART_Popup"
AllowsTransparency="True"
PlacementTarget="{BindingElementName=PART_ToggleButton}"
IsOpen="{BindingIsDropDownOpen,RelativeSource={RelativeSourceTemplatedParent},Mode=TwoWay}"
Placement="Bottom"StaysOpen="False">
<controls:SmallPanelx:Name="PART_DropDown"
MinWidth="{TemplateBindingFrameworkElement.ActualWidth}"
Margin="24,2,24,24"
MaxHeight="{TemplateBindingMaxDropDownHeight}"
RenderTransformOrigin=".5,0"
SnapsToDevicePixels="True">
<controls:SmallPanel.RenderTransform>
<ScaleTransformScaleY="0"/>
</controls:SmallPanel.RenderTransform>
<Border
Name="PART_DropDownBorder"
Background="{TemplateBindingBackground}"
BorderBrush="{TemplateBindingBorderBrush}"
BorderThickness="{TemplateBindingBorderThickness}"
SnapsToDevicePixels="True"
CornerRadius="{BindingPath=(helpers:ElementHelper.CornerRadius),RelativeSource={RelativeSourceTemplatedParent}}"
UseLayoutRounding="True"
Effect="{StaticResourcePopupShadowDepth}"/>
<GridClipToBounds="False"
Margin="0,8">
<Grid.RowDefinitions>
<RowDefinitionHeight="Auto"/>
<RowDefinitionHeight="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBoxx:Name="PART_TextBox"
Margin="6,0"
helpers:ElementHelper.Watermark="{BindingSearchWatermark,RelativeSource={RelativeSourceTemplatedParent}}"/>
<CheckBoxx:Name="PART_SelectAll"
Grid.Row="1"
Margin="5,4"
Visibility="{TemplateBindingIsSelectAllActive,Converter={StaticResourcebool2VisibilityConverter}}"
Content="{TemplateBindingSelectAllContent}"/>
<controls:MultiSelectListBoxx:Name="PART_Selector"
Grid.Row="2"
BorderThickness="1,0,1,0"
DisplayMemberPath="{TemplateBindingDisplayMemberPath}"
SelectedValuePath="{TemplateBindingSelectedValuePath}"
MinHeight="{TemplateBindingMinHeight}"
ItemsSource="{TemplateBindingItemsSource}"
SelectionMode="Multiple"
VerticalContentAlignment="{TemplateBindingVerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBindingHorizontalContentAlignment}"
ItemContainerStyle="{StaticResourceDefaultMultiSelectComboBoxItem}"
ScrollViewer.HorizontalScrollBarVisibility="{BindingScrollViewer.HorizontalScrollBarVisibility,RelativeSource={RelativeSourceTemplatedParent}}"
ScrollViewer.CanContentScroll="{BindingScrollViewer.CanContentScroll,RelativeSource={RelativeSourceTemplatedParent}}"
BorderBrush="{TemplateBindingBorderBrush}">
</controls:MultiSelectListBox>
<controls:MultiSelectListBoxx:Name="PART_SearchSelector"
Grid.Row="2"
BorderThickness="1,0,1,0"
BorderBrush="{TemplateBindingBorderBrush}"
DisplayMemberPath="{TemplateBindingDisplayMemberPath}"
SelectedValuePath="{TemplateBindingSelectedValuePath}"
MinHeight="{TemplateBindingMinHeight}"
ItemsSource="{TemplateBindingItemsSourceSearch}"
SelectionMode="Multiple"
VerticalContentAlignment="{TemplateBindingVerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBindingHorizontalContentAlignment}"
ItemContainerStyle="{StaticResourceDefaultMultiSelectComboBoxItem}"
ScrollViewer.HorizontalScrollBarVisibility="{BindingScrollViewer.HorizontalScrollBarVisibility,RelativeSource={RelativeSourceTemplatedParent}}"
ScrollViewer.CanContentScroll="{BindingScrollViewer.CanContentScroll,RelativeSource={RelativeSourceTemplatedParent}}"
Visibility="Collapsed">
</controls:MultiSelectListBox>
</Grid>
</controls:SmallPanel>
</Popup>
</controls:SmallPanel>
<ControlTemplate.Triggers>
<TriggerSourceName="PART_ToggleButton"Property="IsChecked"Value="True">
<Trigger.EnterActions>
<BeginStoryboadx:Name="BeginStoryboardOpenStoryboard"Storyboard="{StaticResourceOpenStoryboard}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboardBeginStoryboardName="BeginStoryboardOpenStoryboard"/>
</Trigger.ExitActions>
</Trigger>
<TriggerSourceName="PART_ToggleButton"Property="IsChecked"Value="False">
<Trigger.EnterActions>
<BeginStoryboardx:Name="BeginStoryboardCloseStoryboard"Storyboard="{StaticResourceCloseStoryboard}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboardBeginStoryboardName="BeginStoryboardCloseStoryboard"/>
</Trigger.ExitActions>
</Trigger>
<TriggerProperty="IsMouseOver"Value="True">
<SetterProperty="BorderBrush"TargetName="PART_Border"Value="{DynamicResourcePrimaryNormalSolidColorBrush}"/>
</Trigger>
<TriggerSourceName="PART_Popup"Property="AllowsTransparency"Value="True">
<SetterTargetName="PART_DropDownBorder"Property="Margin"Value="0,2,0,0"/>
</Trigger>
<TriggerProperty="Text"Value="">
<SetterProperty="Visibility"TargetName="PART_Watermark"Value="Visible"/>
</Trigger>
<TriggerProperty="Text"Value="{x:Null}">
<SetterProperty="Visibility"TargetName="PART_Watermark"Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
4)创建 MultiSelectSearchComboBoxExample.xaml 代码如下:
<Grid>
<Grid.RowDefinitions>
<RowDefinitionHeight="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ButtonContent="获取选中"
VerticalAlignment="Bottom"
HorizontalAlignment="Center"
Click="Button_Click"
Margin="0,20,0,0"
Style="{StaticResourceSuccessPrimaryButton}"/>
<UniformGridColumns="2"Rows="2"Grid.Row="1">
<wd:MultiSelectionSearchComboBox
VerticalContentAlignment="Center"
HorizontalAlignment="Center"
ItemsSource="{BindingDrawings}"
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="{BindingDrawings}"
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 代码如下:
usingSystem.Windows;
usingSystem.Windows.Controls;
namespaceWPFDevelopers.Samples.ExampleViews
{
///<summary>
///MultiSelectComboBoxExample.xaml的交互逻辑
///</summary>
publicpartialclassMultiSelectSearchComboBoxExample:UserControl
{
publicMultiSelectSearchComboBoxExample()
{
InitializeComponent();
}
privatevoidButton_Click(objectsender,System.Windows.RoutedEventArgse)
{
WPFDevelopers.Controls.MessageBox.Show($"{MyMultiSelectionSearchComboBox2.Text}\r\n总共选中:{MyMultiSelectionSearchComboBox2.SelectedItems.Count}条","选中内容",MessageBoxButton.OK,MessageBoxImage.Information);
}
}
}
效果图
以上就是基于WPF实现筛选下拉多选控件的详细内容,更多关于WPF筛选下拉多选控件的资料请关注中国红客联盟其它相关文章!