WPF 实现多选下拉控件

 WPF 实现多选下拉控件

控件名:MultiSelectComboBox

作   者:WPFDevelopersOrg - 驚鏵

原文链接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用.NET40

  • Visual Studio 2022;

  • 创建控件 MultiSelectComboBox 继承 ListBox

    • 依赖属性 IsSelectAllActive 是否支持显示全选,默认 false

    • 依赖属性 SelectAllContent 全选控件的 Content,默认显示 全选

    • 依赖属性 Delimiter 分隔符,默认显示 ;

    • 依赖属性 Text 显示选择的所有 Item

    • 其他与ComboBox 依赖属性一致。

03edfcecdcf4e07d8a9927ae5a4cc6de.jpeg

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>
9bd28f26e08db475285d21e59c08879e.gif

Github|MultiSelectComboBox[2]
码云|MultiSelectComboBox[3]
Github|MultiSelectComboBox.xaml[4]
码云|MultiSelectComboBox.xaml[5]

参考资料

[1]

原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers

[2]

Github|MultiSelectComboBox: https://github.com/WPFDevelopersOrg/WPFDevelopers/tree/master/src/WPFDevelopers.Shared/Controls/MultiSelectComboBox/MultiSelectComboBox.cs

[3]

码云|MultiSelectComboBox: https://gitee.com/WPFDevelopersOrg/WPFDevelopers/tree/master/src/WPFDevelopers.Shared/Controls/MultiSelectComboBox/MultiSelectComboBox.cs

[4]

Github|MultiSelectComboBox: https://github.com/WPFDevelopersOrg/WPFDevelopers/tree/master/src/WPFDevelopers.Shared/Themes/MultiSelectComboBox.xaml

[5]

码云|MultiSelectComboBox: https://gitee.com/WPFDevelopersOrg/WPFDevelopers/tree/master/src/WPFDevelopers.Shared/Themes/MultiSelectComboBox.xaml

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF Combobox是一个常见的下拉列表控件,它能够快速地展示和选择不同的选项。在某些情况下,我们需要实现 Combobox 的多选功能,以便用户能够选择多个选项。本文将为您详细介绍如何使用 WPF Combobox 实现多选实现多选的一种简单的方式是将 WPF Combobox 显示为列表框(ListBox),然后允许用户在列表中选择多个选项。要实现这样的多选功能,需要使用 ItemsControl 和 ListBox 控件。首先,使用ItemsControl将要用于展示的选项集合附加到 Combobox 上。 ```xaml <!--定义ItemsControl--> <ItemsControl ItemsSource="{Binding Selection}"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" Margin="5" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> ``` 其中,`Selection`是选项的集合。接下来,将 Combobox 的模板更改为 ListBox,使其在下拉列表中显示所有选项。 ```xaml <!--定义Combobox--> <ComboBox x:Name="ComboBox"> <ComboBox.Template> <ControlTemplate TargetType="ComboBox"> <Grid> <ToggleButton x:Name="ToggleButton" Content="Click" /> <Popup x:Name="Popup"> <ListBox ItemsSource="{Binding Selection}" SelectionMode="Multiple" /> </Popup> </Grid> </ControlTemplate> </ComboBox.Template> </ComboBox> ``` 在 Combobox 的模板中,使用 ToggleButton 将 Popup 隐藏和显示。Popup 中包含 ListBox,且设置 SelectionMode 属性为 Multiple,使其能够选择多个选项。此时,每个选项在 Popup 中显示为 ListBox 中的一个项,而不是 Combobox 的下拉列表中的一个项。 在编写代码时,需要先将 Combobox 显示为 ListBox,然后使用 Popup 特性将其隐藏。此外,还需要为 ListBox 添加事件处理程序,以便在用户选择选项时更新组合框的选项集合。 ```c# //实现多选 ComboBox.IsEditable = true; var itemsControl = ((ComboBox)ComboBox).Template.FindName("PART_ItemList", ComboBox) as ItemsControl; var listBox = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as ListBox; if (listBox != null) { listBox.SelectionMode = SelectionMode.Multiple; listBox.SelectionChanged += listBox_SelectionChanged; } //更新选项 var listBox = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as ListBox; if (listBox != null) { listBox.SelectionChanged -= listBox_SelectionChanged; for (int i = 0; i < listBox.SelectedItems.Count; ++i) { Selection.Add(listBox.SelectedItems[i].ToString()); } listBox.SelectionChanged += listBox_SelectionChanged; } ``` 最后,用户选择多个选项时,会在 Selection 集合中添加选项,当用户关闭 Popup 时,将更新选项的 Text 和 Popup 的 IsOpen 属性。 如上所述,这是使用 WPF Combobox 实现多选的一种简单方法。我们先将 Combobox 显示为 ListBox,再使用 Popup 特性将Popup隐藏,然后添加事件处理程序以更新选项集合。这种方式虽然看起来有点繁琐,但要实现多选需要的代码量很少,而且在使用上比一些自定义控件的方式更灵活简便。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值