C#-下拉多选

简介: 本例通过模板实现支持多选的下拉框,使用CheckBox自定义ComboBox项,并在选中时将内容拼接显示在输入框中。

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

当用户勾选下拉项时,下拉框中显示勾选的内容,并用逗号隔开,这里使用模板实现,在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(',');
    }
}

image.png

完整参考代码

//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);
            }
        }
    }
}
目录
相关文章
|
2月前
|
前端开发 程序员
墨刀原型图的原理、与UI设计图的区别及转换方法详解-卓伊凡|贝贝
墨刀原型图的原理、与UI设计图的区别及转换方法详解-卓伊凡|贝贝
231 24
墨刀原型图的原理、与UI设计图的区别及转换方法详解-卓伊凡|贝贝
|
2月前
|
人工智能 自然语言处理 API
构建可落地的企业AI Agent,背后隐藏着怎样的技术密码?
三桥君深入解析企业AI Agent技术架构,涵盖语音识别、意图理解、知识库协同、语音合成等核心模块,探讨如何实现业务闭环与高效人机交互,助力企业智能化升级。
193 6
|
2月前
|
数据采集 分布式计算 DataWorks
ODPS在某公共数据项目上的实践
本项目基于公共数据定义及ODPS与DataWorks技术,构建一体化智能化数据平台,涵盖数据目录、归集、治理、共享与开放六大目标。通过十大子系统实现全流程管理,强化数据安全与流通,提升业务效率与决策能力,助力数字化改革。
78 4
|
2月前
|
人工智能 弹性计算 API
再不玩通义 VACE 模型你就过时了!一个模型搞定所有视频任务
介绍通义的开源模型在 ecs 或 acs 场景如何一键部署和使用,如何解决不同视频生成场景的问题。
|
2月前
|
数据可视化 Java 数据库连接
Dataphin JDBC:助您实现数据权限的集中管理
Dataphin JDBC提供了统一访问Dataphin中数据的功能,助您实现数据权限的集中式管理。
132 3
|
2月前
|
人工智能 测试技术 API
Apifox 和 Apipost如何选?2025企业API开发工具选型需求分析及建议
本文对比了 Apipost 与 Apifox 在 AI 功能及 API 功能上的差异,指出 Apipost 凭借 AI 一键补全文档、智能提取 API 文档、AI 断言、模拟测试数据、生成用例、参数更新、脚本生成、全局搜索等能力,显著提升开发效率与质量。同时,Apipost 在离线使用、一键分享、OpenAPI 格式支持、多协议适配、数据库导入、模拟数据、压测功能等基础 API 能力上亦全面领先。在AI时代的2025年,API + AI是Apipost将AI技术融合行业应用的最佳典范,这种趋势下,也说明Apipost 更能助力企业与开发者实现高效智能开发。
131 2
|
2月前
|
SQL 运维 自然语言处理
Dataphin智能化重磅升级!编码难题一扫光,开发运维更高效!
Dataphin重磅推出三大核心智能化能力:智能代码助手提升SQL开发效率;智能运维助手实现移动化任务管理;智能分析通过自然语言生成SQL,助力数据价值释放。未来将持续开放智能ETL、安全助手等能力,助力企业构建高效、稳定的数据资产体系。
315 0
|
3月前
|
人工智能 监控 安全
人人都是造梦者:AI时代的创意落地指南
有好想法因为"不会技术"而只能停留在脑海里?如果技术门槛不再是阻碍,你最想实现什么?在发现好想法后,如何落地自己的AI创意?这个过程可能需要哪些东西?本文手把手教你如何让自己的创意落地。
216 16
人人都是造梦者:AI时代的创意落地指南
|
2月前
|
人工智能 测试技术 编译器
Python语言从2.7到3.14的能力变化与演进逻辑
Python自2008年进入3.0时代以来,经历了持续演进与革新。十六年间,从语言设计、标准库优化到性能提升、虚拟机改进,Python不断适应人工智能、云计算和微服务等技术的发展需求。本文全面梳理了Python 3发布以来的重要变化,涵盖编程风格现代化、类型系统完善、类库生态调整、性能优化突破以及虚拟机技术创新等多个维度,展示了Python如何在保持简洁易用的同时,实现高效、稳定和可扩展的工程能力。未来,Python将在性能、类型安全和云原生等方面持续进化,进一步巩固其在现代软件开发中的核心地位。
294 30
|
2月前
|
API 数据安全/隐私保护 开发者
企业微信自动加好友软件,导入手机号批量添加微信好友,python版本源码分享
代码展示了企业微信官方API的合规使用方式,包括获取access_token、查询部门列表和创建用户等功能