编程笔记

C#-下拉多选

12/17/2024 9:11:18 PM
0

如何让下拉项能够支持多选?

当用户勾选下拉项时,下拉框中显示勾选的内容,并用逗号隔开,这里使用模板实现,在Combobox.ItemTemplate中使用Checkbox,参考代码如下:

<ComboBox Width="100" 
          IsEditable="True" 
          IsReadOnly="True" 
          Text="{Binding ItemText}"
          ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Name}"
                      IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                      Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=ComboBox}}">
            </CheckBox>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

如果你不设置CheckBox的宽度,这里点击到非CheckBox的区域的时候,ComboBox会显示选中的行,这显然不是我们想要的效果,简单的处理,即将ChecBox尽可能的占据ComboBoxItem的区域,所以我们在这里设置了它的宽度,并且将ComboBoxItem的Margin,Padding设置为0。

如何让选中的项都显示在下拉框中?

ComboBox的Text绑定了ItemText,IsChecked绑定了项的IsChecked属性,在属性改变时我们拼接ItemText的内容,参考代码如下:

private void Item_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    if (e.PropertyName == "IsChecked")
    {
        string strItems = "";
        foreach(var item in Items)
        {
            if (item.IsChecked)
            {
                strItems += item.Name+",";
            }
        }
        ItemText = strItems.TrimEnd(',');
    }
}

效果

完整参考代码

//mainwindow.xaml
<Window x:Class="ComboBoxTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ComboBoxTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="ComboBoxItem">
            <Setter Property="Margin" Value="0"></Setter>
            <Setter Property="Padding" Value="0"></Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <WrapPanel>
            <ComboBox Width="100" 
                      IsEditable="True" 
                      IsReadOnly="True" 
                      Text="{Binding ItemText}"
                      ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <CheckBox Content="{Binding Name}"
                                  IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                                  Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=ComboBox}}">
                        </CheckBox>
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
        </WrapPanel>
    </Grid>
</Window>
//mainwindow.xaml.cs
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;

namespace ComboBoxTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }
    }
    public class Item: ObservableObject
    {
        private string m_Name;
        public string Name
        {
            get { return m_Name; }
            set { SetProperty(ref m_Name, value); }
        }
        private bool m_IsChecked;
        public bool IsChecked
        {
            get
            {
                return m_IsChecked;
            }
            set
            {
                SetProperty(ref m_IsChecked, value);
            }
        }
    }
    public class MainWindowViewModel:ObservableObject
    {
        public MainWindowViewModel() 
        {
            Item item = new Item();
            item.Name = "123";
            item.PropertyChanged += Item_PropertyChanged;
            Items.Add(item);

            Item item1 = new Item();
            item1.Name = "456";
            item1.PropertyChanged += Item_PropertyChanged;
            Items.Add(item1);

            Item item2 = new Item();
            item2.Name = "789";
            item2.PropertyChanged += Item_PropertyChanged;
            Items.Add(item2);
        }

        private void Item_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsChecked")
            {
                string strItems = "";
                foreach(var item in Items)
                {
                    if (item.IsChecked)
                    {
                        strItems += item.Name+",";
                    }
                }
                ItemText = strItems.TrimEnd(',');
            }
        }

        private ObservableCollection<Item> m_Items = new ObservableCollection<Item>();
        public ObservableCollection<Item> Items
        {
            get
            {
                return m_Items;
            }
            set
            {
                SetProperty(ref m_Items,value);
            }
        }
        private string m_ItemText;
        public string ItemText
        {
            get
            {
                return m_ItemText;
            }
            set
            {
                SetProperty(ref m_ItemText,value);
            }
        }
    }
}

友情链接

Copyright @2021-2025 关于