基于WPF實(shí)現(xiàn)多選下拉控件的示例代碼
WPF 實(shí)現(xiàn)多選下拉控件
框架使用.NET40
;
Visual Studio 2022
;
創(chuàng)建控件 MultiSelectComboBox
繼承 ListBox
。
- 依賴屬性
IsSelectAllActive
是否支持顯示全選,默認(rèn)false
。 - 依賴屬性
SelectAllContent
全選控件的Content
,默認(rèn)顯示全選
。 - 依賴屬性
Delimiter
分隔符,默認(rèn)顯示;
。 - 依賴屬性
Text
顯示選擇的所有Item
。 - 其他與
ComboBox
依賴屬性一致。
實(shí)現(xiàn)代碼
1) MultiSelectComboBox.xaml
代碼如下:
using?System; using?System.ComponentModel; using?System.Linq; using?System.Windows; using?System.Windows.Controls; using?System.Windows.Controls.Primitives; using?System.Windows.Input; using?System.Windows.Threading; namespace?WPFDevelopers.Controls { ????public?class?MultiSelectComboBox?:?ListBox ????{ ????????private?const?string?PART_Popup?=?"PART_Popup"; ????????private?const?string?PART_CheckBoxAll?=?"PART_CheckBoxAll"; ????????public?static?readonly?DependencyProperty?IsDropDownOpenProperty?= ????????????DependencyProperty.Register("IsDropDownOpen",?typeof(bool),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(false)); ????????public?static?readonly?DependencyProperty?MaxDropDownHeightProperty ????????????=?DependencyProperty.Register("MaxDropDownHeight",?typeof(double),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(SystemParameters.PrimaryScreenHeight?/?3)); ????????public?static?readonly?DependencyProperty?SelectAllContentProperty?= ????????????DependencyProperty.Register("SelectAllContent",?typeof(object),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata("全選")); ????????public?static?readonly?DependencyProperty?IsSelectAllActiveProperty?= ????????????DependencyProperty.Register("IsSelectAllActive",?typeof(bool),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(false)); ????????public?static?readonly?DependencyProperty?DelimiterProperty?= ????????????DependencyProperty.Register("Delimiter",?typeof(string),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(";")); ????????public?static?readonly?DependencyProperty?TextProperty?= ????????????DependencyProperty.Register("Text",?typeof(string),?typeof(MultiSelectComboBox), ????????????????new?PropertyMetadata(string.Empty,?OnTextChanged)); ????????private?bool?_ignoreTextValueChanged; ????????private?MultiSelectComboBoxItem?_multiSelectComboBoxItem; ????????private?Popup?_popup; ????????public?bool?IsDropDownOpen ????????{ ????????????get?=>?(bool)GetValue(IsDropDownOpenProperty); ????????????set?=>?SetValue(IsDropDownOpenProperty,?value); ????????} ????????[Bindable(true)] ????????[Category("Layout")] ????????[TypeConverter(typeof(LengthConverter))] ????????public?double?MaxDropDownHeight ????????{ ????????????get?=>?(double)GetValue(MaxDropDownHeightProperty); ????????????set?=>?SetValue(MaxDropDownHeightProperty,?value); ????????} ????????public?object?SelectAllContent ????????{ ????????????get?=>?GetValue(SelectAllContentProperty); ????????????set?=>?SetValue(SelectAllContentProperty,?value); ????????} ????????public?bool?IsSelectAllActive ????????{ ????????????get?=>?(bool)GetValue(IsSelectAllActiveProperty); ????????????set?=>?SetValue(IsSelectAllActiveProperty,?value); ????????} ????????public?string?Delimiter ????????{ ????????????get?=>?(string)GetValue(DelimiterProperty); ????????????set?=>?SetValue(DelimiterProperty,?value); ????????} ????????public?string?Text ????????{ ????????????get?=>?(string)GetValue(TextProperty); ????????????set?=>?SetValue(TextProperty,?value); ????????} ????????private?static?void?OnIsDropDownOpenChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e) ????????{ ????????????var?MultiSelectComboBox?=?(MultiSelectComboBox)d; ????????????if?(!(bool)e.NewValue) ????????????????MultiSelectComboBox.Dispatcher.BeginInvoke(new?Action(()?=>?{?Mouse.Capture(null);?}), ????????????????????DispatcherPriority.Send); ????????} ????????private?static?void?OnTextChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e) ????????{ ????????} ????????protected?override?bool?IsItemItsOwnContainerOverride(object?item) ????????{ ????????????return?item?is?MultiSelectComboBoxItem; ????????} ????????protected?override?DependencyObject?GetContainerForItemOverride() ????????{ ????????????return?new?MultiSelectComboBoxItem(); ????????} ????????protected?override?void?OnSelectionChanged(SelectionChangedEventArgs?e) ????????{ ????????????UpdateText(); ????????????base.OnSelectionChanged(e); ????????} ????????public?override?void?OnApplyTemplate() ????????{ ????????????base.OnApplyTemplate(); ????????????_popup?=?GetTemplateChild(PART_Popup)?as?Popup; ????????????_multiSelectComboBoxItem?=?GetTemplateChild(PART_CheckBoxAll)?as?MultiSelectComboBoxItem; ????????????_multiSelectComboBoxItem.Selected?+=?_MultiSelectComboBoxItem_Selected; ????????????_multiSelectComboBoxItem.Unselected?+=?_MultiSelectComboBoxItem_Unselected; ????????} ????????private?void?_MultiSelectComboBoxItem_Unselected(object?sender,?RoutedEventArgs?e) ????????{ ????????????if?(_ignoreTextValueChanged)?return; ????????????_ignoreTextValueChanged?=?true; ????????????UnselectAll(); ????????????_ignoreTextValueChanged?=?false; ????????????UpdateText(); ????????} ????????private?void?_MultiSelectComboBoxItem_Selected(object?sender,?RoutedEventArgs?e) ????????{ ????????????if?(_ignoreTextValueChanged)?return; ????????????_ignoreTextValueChanged?=?true; ????????????SelectAll(); ????????????_ignoreTextValueChanged?=?false; ????????????UpdateText(); ????????} ????????protected?virtual?void?UpdateText() ????????{ ????????????if?(_ignoreTextValueChanged)?return; ????????????var?newValue?=?string.Join(Delimiter,?SelectedItems.Cast<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; ????????????} ???????????? ????????} ????????protected?object?GetItemDisplayValue(object?item) ????????{ ????????????if?(string.IsNullOrWhiteSpace(DisplayMemberPath)) ????????????{ ????????????????var?property?=?item.GetType().GetProperty("Content"); ????????????????if?(property?!=?null) ????????????????????return?property.GetValue(item,?null); ????????????} ????????????var?nameParts?=?DisplayMemberPath.Split('.'); ????????????if?(nameParts.Length?==?1) ????????????{ ????????????????var?property?=?item.GetType().GetProperty(DisplayMemberPath); ????????????????if?(property?!=?null) ????????????????????return?property.GetValue(item,?null); ????????????} ????????????return?item; ????????} ????} }
2) MultiSelectComboBoxItem.cs
代碼如下:
using?System.Windows.Controls; namespace?WPFDevelopers.Controls { ????public?class?MultiSelectComboBoxItem?:?ListBoxItem ????{ ????} }
3) MultiSelectComboBox.xaml
代碼如下:
<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.MergedDictionaries> ??<BooleanToVisibilityConverter?x:Key="bool2VisibilityConverter"?/> ?<Style?x:Key="DefaultMultiSelectComboBoxItem"?TargetType="{x:Type?controls:MultiSelectComboBoxItem}"> ??<Setter?Property="HorizontalContentAlignment"?Value="{Binding?HorizontalContentAlignment,?RelativeSource={RelativeSource?AncestorType={x:Type?ItemsControl}}}"/> ??<Setter?Property="VerticalContentAlignment"?Value="{Binding?VerticalContentAlignment,?RelativeSource={RelativeSource?AncestorType={x:Type?ItemsControl}}}"/> ??<Setter?Property="SnapsToDevicePixels"?Value="True"/> ??<Setter?Property="Background"?Value="Transparent"/> ??<Setter?Property="BorderBrush"?Value="Transparent"/> ??<Setter?Property="Foreground"?Value="{DynamicResource?RegularTextSolidColorBrush}"/> ??<Setter?Property="BorderThickness"?Value="0"/> ??<Setter?Property="Height"?Value="34"?/> ??<Setter?Property="Margin"?Value="1,0"?/> ??<Setter?Property="Padding"?Value="6,0"/> ??<Setter?Property="Cursor"?Value="Hand"?/> ??<Setter?Property="Template"> ???<Setter.Value> ????<ControlTemplate?TargetType="{x:Type?controls:MultiSelectComboBoxItem}"> ?????<Border?x:Name="PART_Border" ???????BorderBrush="{TemplateBinding?BorderBrush}" ???????BorderThickness="{TemplateBinding?BorderThickness}" ???????Background="{TemplateBinding?Background}" ???????SnapsToDevicePixels="true" ???????Padding="{TemplateBinding?Padding}"> ??????<CheckBox?Foreground="{TemplateBinding?Foreground}" ??????????HorizontalAlignment="Stretch" ??????????VerticalAlignment="{TemplateBinding?VerticalContentAlignment}" ??????????MinHeight="{TemplateBinding?MinHeight}" ??????????Padding="{TemplateBinding?Padding}" ??????????IsChecked="{Binding?IsSelected,RelativeSource={RelativeSource?TemplatedParent},Mode=TwoWay}"> ???????<ContentPresenter?HorizontalAlignment="{TemplateBinding?HorizontalContentAlignment}" ??????????VerticalAlignment="{TemplateBinding?VerticalContentAlignment}" ??????????x:Name="PART_ContentPresenter" ??????????SnapsToDevicePixels="{TemplateBinding?SnapsToDevicePixels}" ??????????TextElement.Foreground="{TemplateBinding?Foreground}"/> ??????</CheckBox> ?????</Border> ?????<ControlTemplate.Triggers> ??????<Trigger?Property="IsMouseOver"?Value="True"> ???????<Setter?Property="Background"?Value="{DynamicResource?DefaultBackgroundSolidColorBrush}"/> ??????</Trigger> ?????</ControlTemplate.Triggers> ????</ControlTemplate> ???</Setter.Value> ??</Setter> ?</Style> ?<Style?TargetType="{x:Type?controls:MultiSelectComboBox}"> ??<Setter?Property="ScrollViewer.HorizontalScrollBarVisibility"?Value="Auto"?/> ??<Setter?Property="ScrollViewer.VerticalScrollBarVisibility"?Value="Auto"?/> ??<Setter?Property="ScrollViewer.CanContentScroll"?Value="True"?/> ??<Setter?Property="SelectionMode"?Value="Multiple"/> ??<Setter?Property="MinWidth"?Value="120"?/> ??<Setter?Property="MinHeight"?Value="{StaticResource?MinHeight}"?/> ????????<Setter?Property="Height"?Value="{StaticResource?MinHeight}"?/> ??<Setter?Property="ItemContainerStyle"?Value="{StaticResource?DefaultMultiSelectComboBoxItem}"/> ??<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:MultiSelectComboBox}"> ?????<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" ?????????Text="{Binding?Text,RelativeSource={RelativeSource?TemplatedParent},Mode=TwoWay}" ?????????Background="{TemplateBinding?Background}" ?????????SelectionBrush="{DynamicResource?WindowBorderBrushSolidColorBrush}" ?????????IsReadOnly="True"?Style="{x:Null}"?/> ?????? ??????<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/> ?????????</Grid.RowDefinitions> ?????????<controls:MultiSelectComboBoxItem?x:Name="PART_CheckBoxAll" ????????????????????Visibility="{TemplateBinding?IsSelectAllActive,Converter={StaticResource?bool2VisibilityConverter}}" ????????????????????Style="{TemplateBinding?ItemContainerStyle}" ????????????????????Content="{TemplateBinding?SelectAllContent}"/> ?????????<ScrollViewer?x:Name="DropDownScrollViewer"?Grid.Row="1" ???????????????ScrollViewer.VerticalScrollBarVisibility="Auto"> ??????????<ItemsPresenter?x:Name="ItemsPresenter" ???????????????KeyboardNavigation.DirectionalNavigation="Contained" ???????????????SnapsToDevicePixels="{TemplateBinding?SnapsToDevicePixels}"/> ?????????</ScrollViewer> ????????</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> ?????</ControlTemplate.Triggers> ????</ControlTemplate> ???</Setter.Value> ??</Setter> ?</Style> </ResourceDictionary>
4) MultiSelectComboBoxExample.xaml
代碼如下:
<UserControl?x: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:HospitalList?x:Key="myHospitalList"/> ????</UserControl.Resources> ????<controls:CodeViewer> ????????<UniformGrid?Columns="2"> ????????????<wpfdev:MultiSelectComboBox ????????????????VerticalContentAlignment="Center"? ????????????????HorizontalAlignment="Center" ????????????????Delimiter="^"?Width="200"> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?1</wpfdev:MultiSelectComboBoxItem> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?2</wpfdev:MultiSelectComboBoxItem> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?3</wpfdev:MultiSelectComboBoxItem> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?4</wpfdev:MultiSelectComboBoxItem> ????????????????<wpfdev:MultiSelectComboBoxItem>Option?5</wpfdev:MultiSelectComboBoxItem> ????????????</wpfdev:MultiSelectComboBox> ????????????<wpfdev:MultiSelectComboBox?VerticalContentAlignment="Center"? ?????????????????????????????????????????HorizontalAlignment="Center" ?????????????????????????????????????????IsSelectAllActive="True" ?????????????????????????????ItemsSource="{Binding?Source={StaticResource?myHospitalList}}" ?????????????????????????????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實(shí)現(xiàn)多選下拉控件的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于WPF多選下拉控件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#實(shí)現(xiàn)HSL顏色值轉(zhuǎn)換為RGB的方法
這篇文章主要介紹了C#實(shí)現(xiàn)HSL顏色值轉(zhuǎn)換為RGB的方法,涉及C#數(shù)值判定與轉(zhuǎn)換的相關(guān)技巧,需要的朋友可以參考下2015-06-06C#使用Gembox.SpreadSheet向Excel寫(xiě)入數(shù)據(jù)及圖表的實(shí)例
下面小編就為大家分享一篇C#使用Gembox.SpreadSheet向Excel寫(xiě)入數(shù)據(jù)及圖表的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12Unity技術(shù)手冊(cè)之Toggle切換使用實(shí)例
這篇文章主要為大家介紹了Unity技術(shù)手冊(cè)之Toggle切換使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11