C# WINFORM多选下拉框实现

效果如如下:

思路
1.基于原生控件ComboBox和CheckedListBox来实现,其中ComboBox负责显示多选结果和提供下拉按钮,然后CheckedListBox负责提供下拉多选操作
2.ComboBox设置为自绘,DropDownStyle为ComboBoxStyle.DropDown,下拉高度为1,属性代码设置代码参考如下:
ComboBox = new ComboBox();
ComboBox.Width = 150;
ComboBox.DrawMode = DrawMode.OwnerDrawFixed;
ComboBox.IntegralHeight = false;
ComboBox.DroppedDown = false;
ComboBox.DropDownHeight = 1;
ComboBox.Margin = new Padding(0);
ComboBox.Location = new Point(0, 0);
ComboBox.DropDownStyle = ComboBoxStyle.DropDown;
ComboBox.AutoCompleteSource = AutoCompleteSource.ListItems;
3.CheckedListBox
属性CheckOnClick
设置为true
,同时初始化为不可见,参考代码如下:
CheckedListBox = new CheckedListBox();
CheckedListBox.CheckOnClick = true;
CheckedListBox.BorderStyle = BorderStyle.Fixed3D;
CheckedListBox.Visible = false;
CheckedListBox.Margin = new Padding(0);
4.然后就是处理控件的事件响应了,其中ComboBox
需要处理事件MouseDown
,MouseLeave
和DropDown
,代码如下:
ComboBox.MouseDown += (ss, se) =>
{
ComboBox.DroppedDown = false;
};
ComboBox.MouseLeave += (ss, se) =>
{
// 不在下拉区则隐藏下拉
var curMousePos = this.PointToClient(Control.MousePosition);
var downArea = CheckedListBox.Location;
if (curMousePos.X < downArea.X || curMousePos.X > (downArea.X + CheckedListBox.Width)
|| curMousePos.Y < downArea.Y || curMousePos.Y > (downArea.Y + CheckedListBox.Height))
{
CheckedListBox.Hide();
}
};
ComboBox.DropDown += (ss, se) =>
{
// 显示下拉多选框
CheckedListBox.Items.Clear();
// 添加并设置选中项
var lastChecked = ComboBox.Tag as List<string>;
ComboBox.BeginUpdate();
foreach (var v in this.Items)
{
var ck = false;
if(lastChecked != null && lastChecked.IndexOf(v.ToString())>=0)
{
ck = true;
}
CheckedListBox.Items.Add(v, ck);
}
// 显示下拉框
CheckedListBox.Width = ComboBox.Width;
CheckedListBox.ItemHeight = ComboBox.ItemHeight;
CheckedListBox.Size = new Size(ComboBox.DropDownWidth, this.Items.Count * 18);
CheckedListBox.Location = new Point(ComboBox.Left, ComboBox.Height);
this.Controls.Add(CheckedListBox);
CheckedListBox.Visible = true;
ComboBox.EndUpdate();
};
5.还要继续处理控件CheckedListBox
的事件,包括MouseUp
和MouseLeave
,代码如下:
CheckedListBox.MouseUp += (ss, se) =>
{
// 更新ComboBox显示文本
var lst = new List<string>();
foreach (var v in CheckedListBox.CheckedItems)
{
lst.Add(v.ToString());
}
ComboBox.Text = string.Join(",", lst);
ComboBox.Tag = lst;
};
CheckedListBox.MouseLeave += (ss, se) =>
{
// 隐藏下拉多选框
CheckedListBox.Hide();
};
完整代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ControlEx
{
#region 简单的多选下拉框
public class MultiComboBox : UserControl
{
#region 属性
public ComboBox ComboBox { get; set; }
public CheckedListBox CheckedListBox { get; set; }
public ComboBox.ObjectCollection Items
{
get
{
return ComboBox?.Items;
}
}
#endregion
/// <summary>
/// 多选下拉框
/// </summary>
public MultiComboBox()
{
// 面板
this.VerticalScroll.Enabled = true;
this.AutoSize = true;
// 多选列表
CheckedListBox = new CheckedListBox();
CheckedListBox.CheckOnClick = true;
CheckedListBox.BorderStyle = BorderStyle.Fixed3D;
CheckedListBox.Visible = false;
CheckedListBox.Margin = new Padding(0);
CheckedListBox.MouseUp += (ss, se) =>
{
// 更新ComboBox显示文本
var lst = new List<string>();
foreach (var v in CheckedListBox.CheckedItems)
{
lst.Add(v.ToString());
}
ComboBox.Text = string.Join(",", lst);
ComboBox.Tag = lst;
};
CheckedListBox.MouseLeave += (ss, se) =>
{
// 隐藏下拉多选框
CheckedListBox.Hide();
};
// 下拉框
ComboBox = new ComboBox();
ComboBox.Width = 150;
ComboBox.DrawMode = DrawMode.OwnerDrawFixed;
ComboBox.IntegralHeight = false;
ComboBox.DroppedDown = false;
ComboBox.DropDownHeight = 1;
ComboBox.Margin = new Padding(0);
ComboBox.Location = new Point(0, 0);
ComboBox.DropDownStyle = ComboBoxStyle.DropDown;
ComboBox.AutoCompleteSource = AutoCompleteSource.ListItems;
ComboBox.MouseDown += (ss, se) =>
{
ComboBox.DroppedDown = false;
};
ComboBox.MouseLeave += (ss, se) =>
{
// 不在下拉区则隐藏下拉
var curMousePos = this.PointToClient(Control.MousePosition);
var downArea = CheckedListBox.Location;
if (curMousePos.X < downArea.X || curMousePos.X > (downArea.X + CheckedListBox.Width)
|| curMousePos.Y < downArea.Y || curMousePos.Y > (downArea.Y + CheckedListBox.Height))
{
CheckedListBox.Hide();
}
};
ComboBox.DropDown += (ss, se) =>
{
// 显示下拉多选框
CheckedListBox.Items.Clear();
// 添加并设置选中项
var lastChecked = ComboBox.Tag as List<string>;
ComboBox.BeginUpdate();
foreach (var v in this.Items)
{
var ck = false;
if(lastChecked != null && lastChecked.IndexOf(v.ToString())>=0)
{
ck = true;
}
CheckedListBox.Items.Add(v, ck);
}
// 显示下拉框
CheckedListBox.Width = ComboBox.Width;
CheckedListBox.ItemHeight = ComboBox.ItemHeight;
CheckedListBox.Size = new Size(ComboBox.DropDownWidth, this.Items.Count * 18);
CheckedListBox.Location = new Point(ComboBox.Left, ComboBox.Height);
this.Controls.Add(CheckedListBox);
CheckedListBox.Visible = true;
ComboBox.EndUpdate();
};
// 添加控件
this.Controls.Add(ComboBox);
}
}
#endregion
}
测试代码
var panel = this.flowLayoutPanelMain;
var dropDown = new ControlEx.MultiComboBox();
dropDown.Items.AddRange(new string[] { "选项1", "选项2", "选项3", "选项4", "选项5" });
panel.Controls.Add(dropDown);