基于WPF实现多选下拉控件的示例代码
wpF 实现多选下拉控件
框架使用.NET40;
Visual Studio 2022;
创建控件 MultiSelectComboBox 继承 ListBox 。
- 依赖属性
IsSelectAllActive是否支持显示全选,默认false。 - 依赖属性
SelectAllContent全选控件的Content,默认显示全选。 - 依赖属性
Delimiter分隔符,默认显示;。 - 依赖属性
Text显示选择的所有Item。 - 其他与
ComboBox依赖属性一致。

实现代码
1) MultiSelectComboBox.xaml 代码如下:
usingSystem;
usingSystem.ComponentModel;
usingSystem.Linq;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.W编程indows.Controls.Primitives;
usingSystem.Windows.Input;
usingSystem.Windows.Threading;
namespaceWPFDevelopers.Controls
{
publicclassMultiSelectComboBox:ListBox
{
privateconststringPART_Popup="PART_Popup";
privateconststringPART_CheckBoxAll="PART_CheckBoxAll";
publicstaticreadonlyDependencyPropertyIsDropDownOpenProperty=
DependencyProperty.Register("IsDropDownOpen",typeof(bool),typeof(MultiSelectComboBox),
newPropertyMetadata(false));
publicstaticreadonlyDependencyPropertyMaxDropDownHeightProperty
=DependencyProperty.Register("MaxDropDownHeight",typeof(double),typeof(MultiSelectComboBox),
newPropertyMetadata(SystemParameters.PrimaryScreenHeight/3));
publicstaticreadonlyDependencyPropertySelectAllContentProperty=
DependencyProperty.Register("SelectAllContent",typeof(object),typeof(MultiSelectComboBox),
newPropertyMetadata("全选"));
publicstaticreadonlyDependencyPropertyIsSelectAllActiveProperty=
DependencyProperty.Register("IsSelectAllActive",typeof(bool),typeof(MultiSelectComboBox),
newPropertyMetadata(false));
publicstaticreadonlyDependencyPropertyDelimiterProperty=
DependencyProperty.Register("Delimiter",typeof(string),typeof(MultiSelectComboBox),
newPropertyMetadata(";"));
publicstaticreadonlyDependencyPropertyTextProperty=
DependencyProperty.Register("Text",typeof(string),typeof(MultiSelectComboBox),
newPropertyMetadata(string.Empty,OnTextChanged));
privatebool_ignoreTextValueChanged;
privateMultiSelectComboBoxItem_multiSelectComboBoxItem;
privatePopup_popup;
publicboolIsDropDownOpen
{
get=>(bool)GetValue(IsDropDownOpenProperty);
set=>SetValue(IsDropDownOpenProperty,value);
}
[Bindable(true)]
[Category("Layout")]
[TypeConverter(typeof(LengthConverter))]
publicdoubleMaxDropDownHeight
{
get=>(double)GetValue(MaxDropDownHeightProperty);
set=>SetValue(MaxDropDownHeightProperty,value);
}
publicobjectSelectAllContent
{
get=>GetValue(SelectAllContentProperty);
set=>SetValue(SelectAllContentProperty,value);
}
publicboolIsSelectAllActive
{
get=>(bool)GetValue(IsSelectAllActiveProperty);
set=>SetValue(IsSelectAllActiveProperty,value);
}
publicstringDelimiter
{
get=>(string)GetValue(DelimiterProperty);
set=>SetValue(DelimiterProperty,value);
}
publicstringText
{
get=>(string)GetValue(TextProperty);
set=>SetValue(TextProperty,value);
}
privatestaticvoidOnIsDropDownOpenChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)
{
varMultiSelectComboBox=(MultiSelectComboBox)d;
if(!(bool)e.NewValue)
MultiSelectComboBox.Dispatcher.BeginInvoke(newAction(()=>{Mouse.Capture(null);}),
DispatcherPriority.Send);
}
privatestaticvoidOnTextChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)
{
}
protectedoverrideboolIsItemItsOwnContainerOverride(objectitem)
{
returnitemisMultiSelectComboBoxItem;
}
protectedoverrideDependencyObjectGetContainerForItemOverride()
{
returnnewMultiSelectComboBoxItem();
}
protectedoverridevoidOnSelectionChanged(SelectionChangedEventArgse)
{
UpdateText();
base.OnSelectionChanged(e);
}
publicoverridevoidOnApplyTemplate()
{
base.OnApplyTemplate();
_popup=GetTemplateChild(PART_Popup)ASPopup;
_multiSelectComboBoxItem=GetTemplateChild(PART_CheckBoxAll)asMultiSelectComboBoxItem;
_multiSelectComboBoxItem.Selected+=_MultiSelectComboBoxItem_Selected;
_multiSelectComboBoxItem.Unselected+=_MultiSelectComboBoxItem_Unselected;
}
privatevoid_MultiSelectComboBoxItem_Unselected(objectsender,RoutedEventArgse)
{
if(_ignoreTextValueChanged)return;
_ignoreTextValueChanged=true;
UnselectAll();
_ignoreTextValueChanged=false;
UpdateText();
}
privatevoid_MultiSelectComboBoxItem_Selected(objectsender,RoutedEventArgse)
{
if(_ignoreTextValueChanged)return;
_ignoreTextValueChanged=true;
SelectAll();
_ignoreTextValueChanged=false;
UpdateText();
}
protectedvirtualvoidUpdateText()
{
if(_ignoreTextValueChanged)return;
varnewValue=string.Join(Delimiter,SelectedItems.Cast<object>().Select(x=>GetItemDisplayValue(x)));
if(string.IsNullOrWhiteSpace(Text)||!Text.Equals(newValue))
{
_ignoreTextValueChanged=true;
if(_multiSelectComboBoxItem!=null)
_multiSelectComboBoxItem.SetCurrentValue(IsSelectedProperty,SelectedItems.Count==Items.Count);
SetCurrentValue(TextProperty,newValue);
_ignoreTextValueChanged=false;
}
}
protectedobjectGetItemDisplayValue(objectitem)
{
if(string.IsNullOrWhiteSpace(DisplayMemberPath))
{
varproperty=item.GetType().GetProperty("Content");
if(property!=null)
returnproperty.GetValue(item,null);
}
varnameParts=DisplayMemberPath.Split('.');
if(nameParts.Length==1)
{
varproperty=item.GetType().GetProperty(DisplayMemberPath);
if(property!=null)
returnproperty.GetValue(item,null);
}
returnitem;
}
}
}
2) MultiSelectComboBoxItem.cs 代码如下:
usingSystem.Windows.Controls;
namespaceWPFDevelopers.Controls
{
publicclassMultiSelectComboBoxItem:ListBoxItem
{
}
}
3) MultiSelectComboBox.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"/>
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverterx:Key="bool2VisibilityConverter"/>
<Stylex:Key="DefaultMultiSelectComboBoxItem"TargetType="{x:Typecontrols:MultiSelectComboBoxItem}">
<SetterProperty="HorizontalContentAlignment"Value="{BindingHorizontalContentAlignment,RelativeSource={RelativeSourceAncestorType={x:TypeItemsControl}}}"/>
<SetterProperty="VerticalContentAlignment"Value="{BindingVerticalContentAlignment,RelativeSource={RelativeSourceAncestorType={x:TypeItemsControl}}}"/>
<SetterProperty="SnapsToDevicePixels"Value="True"/>
<SetterProperty="Background"Value="Transparent"/>
<SetterProperty="BorderBrush"Value="Transparent"/>
<SetterProperty="Foreground"Value="{DynamicResourceRegularTextSolidColorBrush}"/>
<SetterProperty="BorderThickness"Value="0"/>
<SetterProperty="Height"Value="34"/>
<SetterProperty="Margin"Value="1,0"/>
<SetterProperty="Padding"Value="6,0"/>
<SetterProperty="Cursor"Value="Hand"/>
<SetterProperty="Template">
<Setter.Value>
<ControlTemplateTargetType="{x:Typecontrols:MultiSelect编程客栈ComboBoxItem}">
<Borderx:Name="PART_Border"
BorderBrush="{TemplateBindingBorderBrush}"
BorderThickness="{TemplateBindingBorderThickness}"
Background="{TemplateBindingBackground}"
SnapsToDevicePixels="true"
Padding="{TemplateBindingPadding}">
<CheckBoxForegrowww.devze.comund="{TemplateBindingForeground}"
HorizontalAlignment="Stretch"
VerticalAlignment="{TemplateBindingVerticalContentAlignment}"
MinHeight="{TemplateBindingMinHeight}"
Padding="{TemplateBindingPadding}"
IsChecked="{BindingIsSelected,RelativeSource={RelativeSourceTemplatedParent},Mode=TwoWay}">
<ContentPresenterHorizontalAlignment="{TemplateBindingHorizontalContentAlignment}"
VerticalAlignment="{TemplateBindingVerticalContentAlignment}"
x:Name="PART_ContentPresenter"
SnapsToDevicePixels="{TemplateBindingSnapsToDevicePixels}"
TextElement.Foreground="{TemplateBindingForeground}"/>
</CheckBox>
</Border>
<ControlTemplate.Triggers>
<TriggerProperty="IsMouseover"Value="True">
<SetterProperty="Background"Value="{DynamicResourceDefaultBackgroundSolidColorBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<StyleTargetType="{x:Typecontrols:MultiSelectComboBox}">
<SetterProperty="ScrollViewer.HorizontalScrollBarVisibility"Value="Auto"/>
<SetterProperty="ScrollViewer.VerticalScrollBarVisibility"Value="Auto"/>
<SetterProperty="ScrollViewer.CanContentScroll"Value="True"/>
<SetterProperty="SelectionMode"Value="Multiple"/>
<SetterProperty="MinWidth"Value="120"/>
<SetterProperty="MinHeight"Value="{StaticResourceMinHeight}"/>
<SetterProperty="Height"Value="{StaticResourceMinHeight}"/>
<SetterProperty="ItemContainerStyle"Value="{StaticResourceDefaultMultiSelectComboBoxItem}"/>
<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:MultiSelectComboBox}">
<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>
<controls: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"
Text="{BindingText,RelativeSource={RelativeSourceTemplatedParent},Mode=TwoWay}"
Background="{TemplateBindingBackground}"
SelectionBrush="{DynamicResourceWindowBorderBrushSolidColorBrush}"
IsReadOnly="True"Style="{x:Null}"/>
<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"/>
<RowDefinition/>
</Grid.RowDefinitions>
<controls:MultiSelectComboBoxItemx:Name="PART_CheckBoxAll"
Visibility="{TemplateBindingIsSelectAllActive,Converterandroid={StaticResourcebool2VisibilityConverter}}"
Style="{TemplateBindingItemContainerStyle}"
Content="{TemplateBindingSelectAllContent}"/>
<ScrollViewerx:Name="DropDownScrollViewer"Grid.Row="1"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsPresenterx:Name="ItemsPresenter"
KeyboardNavigation.DirectionalNavigat编程客栈ion="Contained"
SnapsToDevicePixels="{TemplateBindingSnapsToDevicePixels}"/>
</ScrollViewer>
</Grid>
</controls:SmallPanel>
</Popup>
</controls:SmallPanel>
<ControlTemplate.Triggers>
<TriggerSourceName="PART_ToggleButton"Property="IsChecked"Value="True">
<Trigger.EnterActions>
<BeginStoryboardx: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>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
4) MultiSelectComboBoxExample.xaml 代码如下:
<UserControlx:Class="WPFDevelopers.Samples.ExampleViews.MultiSelectComboBoxExample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers" xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls" xmlns:model="clr-namespace:WPFDevelopers.Sample.Models" mc:Ignorable="d" d:DesignHeight="450"d:DesignWidth="800"> <UserControl.Resources> <model:HospitalListx:Key="myHospitalList"/> </UserControl.Resources> <开发者_开发培训;controls:CodeViewer> <UniformGridColumns="2"> <wpfdev:MultiSelectComboBox VerticalContentAlignment="Center" HorizontalAlignment="Center" Delimiter="^"Width="200"> <wpfdev:MultiSelectComboBoxItem>Option1</wpfdev:MultiSelectComboBoxItem> <wpfdev:MultiSelectComboBoxItem>Option2</wpfdev:MultiSelectComboBoxItem> <wpfdev:MultiSelectComboBoxItem>Option3</wpfdev:MultiSelectComboBoxItem> <wpfdev:MultiSelectComboBoxItem>Option4</wpfdev:MultiSelectComboBoxItem> <wpfdev:MultiSelectComboBoxItem>Option5</wpfdev:MultiSelectComboBoxItem> </wpfdev:MultiSelectComboBox> <wpfdev:MultiSelectComboBoxVerticalContentAlignment="Center" HorizontalAlignment="Center" IsSelectAllActive="True" ItemsSource="{BindingSource={StaticResourcemyHospitalList}}" DisplayMemberPath="DoctorName" SelectedValuePath="ID"Width="200"> </wpfdev:MultiSelectComboBox> </UniformGrid> <controls:CodeViewer.SourceCodes> <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/MultiSelectComboBoxExample.xaml" CodeType="Xaml"/> <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/MultiSelectComboBoxExample.xaml.cs" CodeType="CSharp"/> </controls:CodeViewer.SourceCodes> </controls:CodeViewer> </UserControl>
效果图

以上就是基于WPF实现多选下拉控件的示例代码的详细内容,更多关于WPF多选下拉控件的资料请关注我们其它相关文章!
加载中,请稍侯......
精彩评论