在实际应用中,列表控件主要用于显示列表格式的数据,然后供用户选择,常见的列表控件有ComboBox(下拉列表框),ListBox(列表框),CheckedListBox(带复选框的列表框),ListView(带图标的列表框),TreeView(树状结构的列表视图),今天我们以一些简单的小例子,简述列表控件的常见应用方式,仅供学习分享使用,如有不足之处,还请指正。
概述
列表控件,主要是用于列出选项的 Windows 窗体控件,如果要向用户提供可供选择的选项列表,则可以向 Windows 窗体添加各种列表控件。 常见的列表控件主要有以下几种:
- ComboBox,下拉列表组合框,它显示两个部分:顶部部分是一个文本框,允许用户键入列表项。 第二部分是一个列表框,它显示可以从中选择一个项的列表。
- ListBox,列表框,此控件显示一个列表,可以从中选择一个或多个项。
- CheckedListBox,复选列表框,此控件不仅可以如ListBox 控件一样显示项列表,还可在列表中的项旁边显示复选标记,它是 ListBox 控件的扩展,具备ListBox控件的所有功能。
- ListView,显示带图标的项列表,可以使用此控件创建像Windows资源管理器一样的用户界面,该控件有四种视图模式:LargeIcon、SmallIcon、List 和 Details。
- TreeView,树状结构显示控件,它展示节点的层级结构,树视图中的每个节点可能包含其他节点,称为子节点。 TreeView控件可以将父节点,或包含子节点的节点,显示为展开状态或折叠状态。
上述列表控件既有功能相似之处,也有不同之处,在某些情况下是可以互换的。 但是在另一些场景下,一个可能比另一个更适合某个任务。通常,当有建议的选项时,ComboBox是合适的,当你想要将输入限制为列表上的内容时,ListBox是合适的。此外,ComboBox可节省窗体上的空间,在用户单击向下箭头之前不会显示完整列表,因此组合框可以轻松容纳在较小空间中。
数据构造
在本示例中,为了演示了各个列表控件的使用,先构造数据,本示例采用学校(Shcool),院系(Department),专业(Major),年级(Grade),班级(Class)具备层级关系的模型,模型代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;
namespace Okcoder.WinForm.Demo{ public class School { public int Id { get; set; }
public string Name { get; set; }
public List<Department> Departments { get; set; } }
public class Department { public int Id { get; set; }
public string Name { get; set; }
public List<Major> Majors { get; set; } }
public class Major { public int Id { get; set; }
public string Name { get; set; }
public List<Grade> Grades { get; set; } }
public class Grade { public int Id { get; set; }
public string Name { get; set; }
public List<Class> Classes { get; set; } }
public class Class { public int Id { get; set; }
public string Name { get; set; } }}
创建SqlDalHelper,模拟数据库操作,构造示例数据,如下所示:
namespace Okcoder.WinForm.Demo{ public class SqlDalHelper { private List<School> schools;
private List<Like> likes;
private List<Constellation> constellations;
public SqlDalHelper() { InitShcoolList(); InitLikes(); InitConstellations(); }
private void InitShcoolList() { string file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "schools.json"); string json = File.ReadAllText(file); schools = Newtonsoft.Json.JsonConvert.DeserializeObject<List<School>>(json); }
public List<School> QuerySchools(string name) { if (string.IsNullOrEmpty(name)) { return this.schools; } var list = this.schools.Where(item => item.Name.Contains(name)).ToList(); return list; }
public School? GetSchool(int id) { return schools.FirstOrDefault(item => item.Id == id); } }}
ComboBox
ComboBox用于在下拉列表组合框中显示数据,默认情况下,ComboBox 控件显示两个部分:顶部部分是一个文本框,允许用户键入列表项。 第二部分是一个列表框,当点击右侧的下拉箭头时,显示用户可以从中选择一个项的列表。
ComboBox控件的关键属性:
- SelectedIndex,表示控件当前选中项的索引,它是一个int类型的值,还可以通过在代码中更改 SelectedIndex 值,以编程方式变更ComboBox控件的选择项。 如果未选择任何项,则 SelectedIndex 值为 -1。 如果选择列表中的第一项,则 SelectedIndex 值为 0。
- SelectedItem,表示控件当前选择的项,此属性类似于 SelectedIndex,但返回项本身(通常是字符串值)。
- Count,表示控件中Items列表项的数量,Count 属性的值始终比最大可能的 SelectedIndex 值大 1,因为 SelectedIndex 是从零开始计数的。
- Items,表示列表控件包含的列表项集合,可以通过Items属性Add,Remove,RemoveAt,Clear等方法修改Items中值的内容。
- DataSource,表示ComboBox控件的数据源,它是一个可空的object类型,接收实现IList接口或Array类型的数据。
- DisplayMember,表示列表控件需要显示的内容,它通常是绑定的Item项的属性名称或列名。
- ValueMember,表示列表控件的真实Value应的值,它通常是绑定的Item项的属性名称或列名。
ComboBox控件的关键事件:
- SelectedIndexChanged,当ComboxBox控件的选择项发生改变时触发,可以用来响应ComboBox的选择项改变。
说明,ComboBox下拉列表组合框控件可以通过Items属性来添加或删除列表框中的值,也可以通过统一设置数据源(DataSource)方式进行的赋值。
接下来在Form表单的Load方法中,采用DataSource的方式进行赋值,首先通过sqlDalHelper实例的QuerySchools方法获取学校列表,再将ComboBox控件的DataSource属性赋值为schools列表,由于列表中的项是School对象,所以需要通过DisplayMember指定需要显示的属性路径,ValueMember指定真实的Value的属性路径。具体如下所示:
var schools = sqlDalHelper.QuerySchools(string.Empty); this.combSchools.DataSource = schools.ToList(); this.combSchools.DisplayMember = "Name"; this.combSchools.ValueMember = "Id";
运行程序,如下所示:
ListBox
ListBox控件显示一个列表,用户可以从中选择一个或多个项。 如果列表项总数超过可显示的数量,则会自动向 ListBox 控件添加滚动条。ListBox控件的关键属性:
- MultiColumn,表示是否在列表框中显示多列,当属性 MultiColumn 设置为
true时,如果列表项总数超过可显示的数量时,列表框将显示为多列,并显示水平滚动条。 当MultiColumn 属性设置为false 时,如果列表项总数超过可显示的数量时,列表框显示为单列,并出现垂直滚动条。 - ScrollAlwaysVisible,表示滚动条是否一直显示,如果 ScrollAlwaysVisible 设置为
true,则无论项数如何,滚动条都会显示,默认为false。 - SelectionMode,表示一次可以选择多少个列表项,它是一个枚举类型:None表示不可以选择,One 表示一次只能选择一个,MultiSimple表示一次可以选择多个项,MultiExtended表示一次可以选择多个,且可以使用组合键盘,如Shift,Ctrl帮助选择。
- 与ComboBox控件一样,ListBox控件同样具备SelectedIndex,SelectedItem,Count,Items,DataSource,DisplayMember,ValueMember等属性。
ListBox控件的关键事件:
- SelectedIndexChanged,与ComboBox控件一样,ListBox同样具备SelectedIndexChanged事件,用来响应ListBox控件的选择项改变。
同样接在Form表单的Load方法中,采用DataSource的方式进行赋值,首先通过sqlDalHelper实例的QuerySchools方法获取学校列表,再将ComboBox控件的DataSource属性赋值为schools列表,由于列表中的项是School对象,所以需要通过DisplayMember指定需要显示的属性路径,ValueMember指定真实的Value的属性路径。具体如下所示:
lbShcools.DataSource = schools.ToList()lbShcools.DisplayMember = "Name"lbShcools.ValueMember = "Id"lbShcools.MultiColumn = false
当用户选择ListBox中的项时,会触发SelectedIndexChanged,可以用来确定用户选择的项,如下所示:private void lbShcools_SelectedIndexChanged(object sender, EventArgs e){if (lbShcools.SelectedItems != null) { List<string> schools = new List<string>();foreach (var item in this.lbShcools.SelectedItems) {var school = item as School;if (school != null) { schools.Add(school.Name); } }this.lblSchools.Text = string.Join(",\n", schools); }}
运行程序,如下所示:
CheckedListBox
CheckedListBox控件是 ListBox 控件的扩展,它不仅可以显示项列表(如 ListBox 控件),还可在列表中的项旁边显示复选标记。CheckedListBox控件几乎执行ListBox(列表框)执行的所有操作, 两个控件之间的其他差异是,CheckedListBox仅支持 DrawMode.Normal;并且Checked ListBox只能选择一个项目或无项。CheckedListBox可以在设计时使用 字符串集合编辑器 添加项,也可以在运行时使用 Items 属性从集合中动态添加项。
CheckedListBox控件的关键属性:
- CheckedItems,表示选中的项集合,通过遍历可以获取所有被选中的项。也可以通过控件的GetItemChecked 方法来获取项是否被选中,参数为项索引号,返回值true表示被选中,false表示未被选中。
- CheckOnClick,表示当用户点击列表中的项时,列表项的复选框是否改变状态,默认为false:需要先选择项,再点击复选框进行选择。如果设置为true,则点击列表项会同时改变复选框的状态。
- 与ListBox控件一样,CheckedListBox控件同样具备SelectedIndex,SelectedItem,Count,Items,DataSource,DisplayMember,ValueMember,MultiColumn,ColumnWidth等属性。
CheckedListBox控件的关键事件:
- ItemCheck,当CheckedListBox控件的项的复选框的状态发送变化时触发,事件参数ItemCheckEventArgs,包括列表项复选框的前(CurrentValue),后(NewValue)状态,以及项索引(Index)。
说明:Checked和Selected效果不一样,Checked是复选框被选中,Selected是确定已突出显示哪些项。所以CheckedItems和SelectedItems是表示不同的含义。
本示例构造个人爱好列表框,用户可以勾选个人爱好,首先创建Like模型,如下所示:
namespace Okcoder.WinForm.Demo{ public class Like { public int Id { get; set; }
public string Name { get; set; } }}
在SqlDalHelper类中初始化个人爱好列表,并增加QueryLikes接口获取爱好列表,如下所示:private void InitLikes(){ likes = new List<Like>(); likes.Add(new Like() { Id = 1, Name = "足球", }); likes.Add(new Like() { Id = 2, Name = "篮球", }); likes.Add(new Like() { Id = 3, Name = "乒乓球", }); likes.Add(new Like() { Id = 4, Name = "跳舞", }); likes.Add(new Like() { Id = 5, Name = "唱歌", });}
public List<Like> QueryLikes(){return this.likes;}
在Form表单的Load方法中,获取Like列表,并给CheckListBox赋值,如下所示:var likes = sqlDalHelper.QueryLikes();this.chklbLikes.DataSource = likes;this.chklbLikes.DisplayMember = "Name";this.chklbLikes.MultiColumn = true;this.chklbLikes.ColumnWidth = 80;this.chklbLikes.CheckOnClick = true;
注册CheckedListBox控件的ItemCheck事件,可以获取用户选中的项,如下所示:private void chklbLikes_ItemCheck(object sender, ItemCheckEventArgs e){
List<string> likes = new List<string>();foreach (var item in this.chklbLikes.CheckedItems) {var like = item as Like;if (like != null) { likes.Add(like.Name); } }if (e.NewValue == CheckState.Checked) {var like = this.chklbLikes.Items[e.Index] as Like;if (like != null) { likes.Add(like.Name); } }if(e.NewValue==CheckState.Unchecked) {var like = this.chklbLikes.Items[e.Index] as Like;if (like != null) {if (likes.Contains(like.Name)) { likes.Remove(like.Name); } } }this.lblLikes.Text = string.Join(",", likes);
}
在上述示例中,设置了MultiColumn为true,如果一列无法显示时,会显示为多列。运行效果,如下所示:TreeView
TreeView控件展示节点的层级结构,就像在 Windows 操作系统中 Windows 资源管理器功能左侧窗格中显示文件和文件夹一样。树视图中的每个节点可能包含其他节点,称为子节点。 可以将父节点,或包含子节点的节点,显示为展开状态或折叠状态。
TreeView控件的关键属性:
- CheckBoxes,是否在树视图控件中的树节点旁边显示复选框,可以将TreeView中节点的Checked属性设置为true或false进行动态的选择或取消。
- Nodes,获取TreeView的节点集合或子节点集合。
- SelectedNode 属性获取或设置当前选定的节点,通过SelectedNode属性的Nodes属性的Add/Remove方法,可以动态的为当前选择节点添加/删除子节点。
- ImageList,树状列表中节点图像集合,可以通过指定Node节点的ImageIndex属性为树视图中的节点设置正常状态下的默认图像,SelectedImageIndex设置选择状态下的图像。
- Clear方法可以为节点清除所有子节点。如果是TreeView的Clear方法,则清除所有节点;如果是当前选择的节点调用Clear方法,则清除选定节点的子节点。
- FirstNode,获取节点的第一个子节点,LastNode,获取节点的最后一个子节点。
- NextNode,获取节点的下一个同级节点,PrevNode,获取节点的上一个同级节点。
TreeView控件的关键事件:
- AfterSelect,当TreeView的节点被Select时触发此事件,可以用来确定用户点击了哪个节点。
- AfterCheck,当TreeView控件中的节点显示CheckBox且被选中时触发。
在本示例中,当用户选择学校时,会在右侧显示选择学校的详细信息,所以需要在ComboBox的SelectedIndexChanged事件中处理TreeView节点的初始化,如下所示:
private void combSchools_SelectedIndexChanged(object sender, EventArgs e){this.tvSchool.Nodes.Clear();var school = combSchools.SelectedItem as School;if (school != null) {this.lblSchool.Text = school.Name;TreeNode nodeSchool = new TreeNode(); nodeSchool.Text = school.Name;for (int i = 0; i < school.Departments.Count; i++) {var department = school.Departments[i];TreeNode nodeDepartment = new TreeNode(); nodeDepartment.Text = department.Name;for (int j = 0; j < department.Majors.Count; j++) {var major = department.Majors[j];TreeNode nodeMajor = new TreeNode(); nodeMajor.Text = major.Name;for (int k = 0; k < major.Grades.Count; k++) {var grade = major.Grades[k];TreeNode nodeGrade = new TreeNode(); nodeGrade.Text = grade.Name;for (int l = 0; l < grade.Classes.Count; l++) {var cla = grade.Classes[l];TreeNode nodeClass = new TreeNode(); nodeClass.Text = cla.Name; nodeGrade.Nodes.Add(nodeClass); } nodeMajor.Nodes.Add(nodeGrade); }
nodeDepartment.Nodes.Add(nodeMajor); } nodeSchool.Nodes.Add(nodeDepartment); }this.tvSchool.Nodes.Add(nodeSchool); }}
ListView
ListView控件显示带图标的项列表,可以使用ListView创建用户界面,例如 Windows 资源管理器的右窗格。 通过View 属性可以设置ListView的视图模式,共有四种视图模式:
- LargeIcon 模式显示项文本旁边的大图标,如果控件足够大,则这些项会显示在多个列中。
- SmallIcon 模式相同,只不过它显示小图标。
ListView控件的关键属性:
- SelectedItems 属性包含控件中当前选定的项的集合。
- CheckBoxes,是否在ListView控件中的项旁边显示复选框,可以将ListView中项的Checked属性设置为true或false进行动态的选择或取消。
ListView控件的关键事件:
- SelectedIndexChanged,与ComboBox,ListBox控件一样,ListView同样具备SelectedIndexChanged事件,用来响应ListView控件的选择项改变。
本示例采用星座列表图片,首先构造星座模型,如下所示:
namespace Okcoder.WinForm.Demo{ public class Constellation { public int Id { get; set; }
public string Name { get; set; }
public string Nick { get; set; }
public string Desc { get; set; }
public int ImgIndex { get; set; } }}
在SqlDalHelper中构造星座数据,如下所示:
private void InitConstellations(){ constellations = new List<Constellation>(); constellations.Add(new Constellation() { Id = 1, Name = "Aries", Nick = "白羊座", Desc = "03-21至04-19", ImgIndex=0 }); constellations.Add(new Constellation() { Id = 2, Name = "Taurus", Nick = "金牛座", Desc = "04-20至05-20", ImgIndex = 1 }); constellations.Add(new Constellation() { Id = 3, Name = "Gemini", Nick = "双子座", Desc = "05-21至06-21", ImgIndex = 2 }); constellations.Add(new Constellation() { Id = 4, Name = "Cancer", Nick = "巨蟹座", Desc = "06-22至07-22", ImgIndex = 3 }); constellations.Add(new Constellation() { Id = 5, Name = "Leo", Nick = "狮子座", Desc = "07-23至08-22", ImgIndex = 4 }); constellations.Add(new Constellation() { Id = 6, Name = "Virgo", Nick = "处女座", Desc = "08-23至09-22", ImgIndex = 5 }); constellations.Add(new Constellation() { Id = 7, Name = "Libra", Nick = "天秤座", Desc = "09-23至10-23", ImgIndex = 6 }); constellations.Add(new Constellation() { Id = 8, Name = "Scorpio", Nick = "天蝎座", Desc = "10-24至11-22", ImgIndex = 7 }); constellations.Add(new Constellation() { Id = 9, Name = "Sagittarius", Nick = "射手座", Desc = "11-23至12-21", ImgIndex = 8 }); constellations.Add(new Constellation() { Id = 10, Name = "Capricorn", Nick = "摩羯座", Desc = "12-22至01-19", ImgIndex = 9 }); constellations.Add(new Constellation() { Id = 11, Name = "Aquarius", Nick = "水瓶座", Desc = "01-20至01-18", ImgIndex = 10 }); constellations.Add(new Constellation() { Id = 12, Name = "Pisces", Nick = "双鱼座", Desc = "02-19至03-20", ImgIndex = 11 });}
public List<Constellation> QueryConstellations(){return this.constellations;}
在Form表单的Load事件中,获取列表并赋值给ListView控件,如下所示:
private void FrmList2_Load(object sender, EventArgs e){var images = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Constellation")); images = images.OrderBy(item => item).ToArray(); foreach (var image in images) {this.imgList.Images.Add(Image.FromFile(image)); }this.imgList.ImageSize = new Size(100, 100);this.lvConstellations.LargeImageList = this.imgList;this.lvConstellations.MultiSelect = false;this.lvConstellations.View = View.LargeIcon;var constellations = sqlDalHelper.QueryConstellations();if (constellations.Count > 0) { foreach (var constellation in constellations) {this.lvConstellations.Items.Add(new ListViewItem(constellation.Nick, constellation.ImgIndex)); } }}
当ListView控件选择时,显示星座的大图和详细信息,如下所示:
private void lvConstellations_SelectedIndexChanged(object sender, EventArgs e){if (this.lvConstellations.SelectedIndices.Count < 1) {return; } int index = this.lvConstellations.SelectedIndices[0];var constellation = this.sqlDalHelper.QueryConstellations()[index];if (constellation != null) {this.lblName.Text = constellation.Name;this.lblNick.Text = constellation.Nick;this.lblDesc.Text = constellation.Desc;this.pictureBox1.Image = this.imgList.Images[constellation.ImgIndex];this.pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; }}
其中星座图片从网上下载完成后,放在程序根目录下,如下所示:

运行程序,如下所示:

关于本系列的其他文章,可参考如下链接:
1. 基于.NET的Windows窗体编程之WinForms入门简介
2. 基于.NET的Windows窗体编程之WinForms控件简介
3. 基于.NET的Windows窗体编程之WinForms布局简介
5.基于.NET的Windows窗体编程之WinForms数据表格
以上就是《基于.NET的Windows窗体编程之WinForms列表控件》的全部内容,关于更多详细内容,可参考官方文档。希望能够一起学习,共同进步。
阅读原文:https://mp.weixin.qq.com/s/mJK_tMHLijYCc4qmy3Gsww
该文章在 2026/5/9 17:06:01 编辑过