2025-11-16
C#
00

目录

🎯 ListView核心能力解析
📊 五种视图模式全攻略
💡 实战技巧1:快速构建专业ListView
🔥 实战技巧2:动态添加列和数据
⚡ 实战技巧3:智能事件处理
🎨 实战技巧4:自定义排序器
⚡ 实战技巧5:虚拟模式性能优化
🎯 总结与实战建议

还在为复杂的数据列表展示而头疼吗?每次需要显示表格数据时都要重新造轮子?作为WinForms开发中的核心控件,ListView不仅能优雅地处理各种列表展示需求,更是构建专业用户界面的基石。

许多C#开发者在使用ListView时往往停留在基础应用层面,错失了它的强大功能。本文将从实战角度出发,带你深度掌握ListView的高级特性,让你的应用界面瞬间专业起来!

🎯 ListView核心能力解析

📊 五种视图模式全攻略

ListView提供了5种灵活的显示模式,每种都有其独特的应用场景:

  • LargeIcon:适合文件管理器、图片库等场景
  • SmallIcon:适合紧凑型列表显示
  • List:经典的垂直列表布局
  • Details:表格形式,企业应用首选
  • Tile:现代化的磁贴显示

💡 实战技巧1:快速构建专业ListView

很多开发者不知道如何通过代码高效创建ListView。以下是经过实战验证的最佳实践:

C#
namespace AppBasicListView { public partial class Form1 : Form { private ListView listView; private ContextMenuStrip contextMenu; public Form1() { InitializeComponent(); InitializeListView(); LoadSampleData(); SetupEvents(); } private void InitializeListView() { listView = new ListView { Bounds = new Rectangle(new Point(10, 10), new Size(600, 400)), View = View.Details, // 使用表格视图 LabelEdit = true, // 允许编辑标签 MultiSelect = false, // 单选模式 GridLines = true, // 显示网格线 Sorting = SortOrder.Ascending,// 自动排序 FullRowSelect = true, // 整行选择 CheckBoxes = false, // 根据需要启用复选框 HeaderStyle = ColumnHeaderStyle.Clickable, // 可点击列头排序 HideSelection = false, // 失去焦点时保持选择状态 ShowItemToolTips = true // 显示工具提示 }; // 添加列 SetupColumns(); // 创建右键菜单 SetupContextMenu(); this.Controls.Add(listView); } private void SetupColumns() { // 添加列定义 listView.Columns.Add("ID", 60, HorizontalAlignment.Center); listView.Columns.Add("姓名", 120, HorizontalAlignment.Left); listView.Columns.Add("部门", 100, HorizontalAlignment.Left); listView.Columns.Add("职位", 120, HorizontalAlignment.Left); listView.Columns.Add("入职日期", 100, HorizontalAlignment.Center); listView.Columns.Add("薪资", 80, HorizontalAlignment.Right); } private void SetupContextMenu() { contextMenu = new ContextMenuStrip(); var addItem = new ToolStripMenuItem("添加员工", null, AddEmployee_Click); var editItem = new ToolStripMenuItem("编辑员工", null, EditEmployee_Click); var deleteItem = new ToolStripMenuItem("删除员工", null, DeleteEmployee_Click); var refreshItem = new ToolStripMenuItem("刷新", null, RefreshData_Click); contextMenu.Items.AddRange(new ToolStripItem[] { addItem, editItem, deleteItem, new ToolStripSeparator(), refreshItem }); listView.ContextMenuStrip = contextMenu; } private void LoadSampleData() { // 示例数据 var employees = new[] { new { ID = 1, Name = "张三", Dept = "开发部", Position = "高级工程师", HireDate = "2020-01-15", Salary = 12000 }, new { ID = 2, Name = "李四", Dept = "测试部", Position = "测试工程师", HireDate = "2021-03-20", Salary = 8000 }, new { ID = 3, Name = "王五", Dept = "产品部", Position = "产品经理", HireDate = "2019-08-10", Salary = 15000 }, new { ID = 4, Name = "赵六", Dept = "设计部", Position = "UI设计师", HireDate = "2022-02-01", Salary = 9000 }, new { ID = 5, Name = "钱七", Dept = "开发部", Position = "架构师", HireDate = "2018-05-12", Salary = 18000 } }; listView.Items.Clear(); foreach (var emp in employees) { var item = new ListViewItem(emp.ID.ToString()) { Tag = emp.ID, // 存储ID用于后续操作 UseItemStyleForSubItems = false }; item.SubItems.Add(emp.Name); item.SubItems.Add(emp.Dept); item.SubItems.Add(emp.Position); item.SubItems.Add(emp.HireDate); // 薪资列设置颜色 var salarySubItem = item.SubItems.Add($"¥{emp.Salary:N0}"); if (emp.Salary >= 15000) { salarySubItem.ForeColor = Color.Red; salarySubItem.BackColor = Color.LightYellow; } else if (emp.Salary >= 10000) { salarySubItem.ForeColor = Color.Blue; } listView.Items.Add(item); } } private void SetupEvents() { // 双击编辑 listView.DoubleClick += ListView_DoubleClick; // 键盘事件 listView.KeyDown += ListView_KeyDown; // 选择改变事件 listView.SelectedIndexChanged += ListView_SelectedIndexChanged; // 列头点击排序 listView.ColumnClick += ListView_ColumnClick; // 标签编辑事件 listView.BeforeLabelEdit += ListView_BeforeLabelEdit; listView.AfterLabelEdit += ListView_AfterLabelEdit; // 右键菜单打开前检查 contextMenu.Opening += ContextMenu_Opening; } #region 事件处理方法 private void ListView_DoubleClick(object sender, EventArgs e) { if (listView.SelectedItems.Count > 0) { EditEmployee(); } } private void ListView_KeyDown(object sender, KeyEventArgs e) { switch (e.KeyCode) { case Keys.Delete: DeleteEmployee(); break; case Keys.F2: if (listView.SelectedItems.Count > 0) listView.SelectedItems[0].BeginEdit(); break; case Keys.F5: LoadSampleData(); break; } } private void ListView_SelectedIndexChanged(object sender, EventArgs e) { // 可以在这里更新状态栏或其他UI元素 if (listView.SelectedItems.Count > 0) { var item = listView.SelectedItems[0]; this.Text = $"选中员工: {item.SubItems[1].Text} - {item.SubItems[2].Text}"; } else { this.Text = "员工管理系统"; } } private void ListView_ColumnClick(object sender, ColumnClickEventArgs e) { // 简单的列排序实现 listView.ListViewItemSorter = new ListViewColumnSorter(e.Column); listView.Sort(); } private void ListView_BeforeLabelEdit(object sender, LabelEditEventArgs e) { // 可以在这里控制哪些项目可以编辑 // e.CancelEdit = true; // 取消编辑 } private void ListView_AfterLabelEdit(object sender, LabelEditEventArgs e) { if (string.IsNullOrWhiteSpace(e.Label)) { e.CancelEdit = true; MessageBox.Show("员工ID不能为空!", "输入错误", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } private void ContextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e) { // 根据选择状态启用/禁用菜单项 bool hasSelection = listView.SelectedItems.Count > 0; contextMenu.Items[1].Enabled = hasSelection; // 编辑 contextMenu.Items[2].Enabled = hasSelection; // 删除 } #endregion #region 右键菜单事件 private void AddEmployee_Click(object sender, EventArgs e) { // 添加新员工的逻辑 MessageBox.Show("添加员工功能", "功能演示"); } private void EditEmployee_Click(object sender, EventArgs e) { EditEmployee(); } private void DeleteEmployee_Click(object sender, EventArgs e) { DeleteEmployee(); } private void RefreshData_Click(object sender, EventArgs e) { LoadSampleData(); MessageBox.Show("数据已刷新!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } #endregion #region 业务方法 private void EditEmployee() { if (listView.SelectedItems.Count > 0) { var item = listView.SelectedItems[0]; var employeeName = item.SubItems[1].Text; MessageBox.Show($"编辑员工: {employeeName}", "功能演示"); } } private void DeleteEmployee() { if (listView.SelectedItems.Count > 0) { var item = listView.SelectedItems[0]; var employeeName = item.SubItems[1].Text; var result = MessageBox.Show($"确定要删除员工 '{employeeName}' 吗?", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { listView.Items.Remove(item); MessageBox.Show("员工已删除!", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } #endregion } // 列排序器类 public class ListViewColumnSorter : System.Collections.IComparer { private int columnIndex; private SortOrder sortOrder; public ListViewColumnSorter(int column) { columnIndex = column; sortOrder = SortOrder.Ascending; } public int Compare(object x, object y) { ListViewItem itemX = x as ListViewItem; ListViewItem itemY = y as ListViewItem; string textX = itemX.SubItems[columnIndex].Text; string textY = itemY.SubItems[columnIndex].Text; int result; // 尝试数字比较 if (decimal.TryParse(textX.Replace("¥", "").Replace(",", ""), out decimal numX) && decimal.TryParse(textY.Replace("¥", "").Replace(",", ""), out decimal numY)) { result = numX.CompareTo(numY); } else { result = string.Compare(textX, textY); } return sortOrder == SortOrder.Ascending ? result : -result; } } }

image.png

💎 实战要点

  • 优先使用Details视图,用户体验最佳
  • FullRowSelect=true 能显著提升用户操作便利性
  • GridLines在数据密集场景下必不可少

🔥 实战技巧2:动态添加列和数据

传统做法往往代码冗长,这里提供一个高效的封装方案:

C#
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace AppBasicListView { public partial class Form2 : Form { private ListView listView; private Button btnAdd; private Button btnDelete; private Button btnEdit; private TextBox txtSearch; public Form2() { InitializeComponent(); this.Size = new Size(800, 600); this.Text = "ListView完整示例"; this.StartPosition = FormStartPosition.CenterScreen; // 创建ListView listView = new ListView() { Dock = DockStyle.Fill, View = View.Details, FullRowSelect = true, GridLines = true, MultiSelect = false, AllowColumnReorder = true, HeaderStyle = ColumnHeaderStyle.Clickable }; // 创建工具栏 var toolPanel = new Panel() { Height = 40, Dock = DockStyle.Top, Padding = new Padding(5) }; btnAdd = new Button() { Text = "添加", Size = new Size(80, 30), Location = new Point(5, 5) }; btnEdit = new Button() { Text = "编辑", Size = new Size(80, 30), Location = new Point(90, 5) }; btnDelete = new Button() { Text = "删除", Size = new Size(80, 30), Location = new Point(175, 5) }; txtSearch = new TextBox() { Size = new Size(200, 25), Location = new Point(280, 7), PlaceholderText = "输入关键字搜索..." }; // 添加控件到面板 toolPanel.Controls.AddRange(new Control[] { btnAdd, btnEdit, btnDelete, txtSearch }); // 添加到窗体 this.Controls.Add(listView); this.Controls.Add(toolPanel); // 绑定事件 BindEvents(); SetupListView(); AddColumnsAndItems(); } private void SetupListView() { // 启用双缓冲,减少闪烁 typeof(ListView).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) ?.SetValue(listView, true); // 设置ListView样式 listView.BackColor = Color.White; listView.ForeColor = Color.Black; listView.Font = new Font("Microsoft YaHei", 9F); // 启用排序功能 listView.ListViewItemSorter = new ListViewItemComparer(0); } private void AddColumnsAndItems() { // 批量添加列定义 var columns = new[] { new { Name = "ID", Width = 80, Align = HorizontalAlignment.Center, Tag = "string" }, new { Name = "Name", Width = 150, Align = HorizontalAlignment.Left, Tag = "string" }, new { Name = "Description", Width = 250, Align = HorizontalAlignment.Left, Tag = "string" }, new { Name = "CreateTime", Width = 150, Align = HorizontalAlignment.Center, Tag = "datetime" }, new { Name = "Status", Width = 100, Align = HorizontalAlignment.Center, Tag = "string" } }; // 清空现有列 listView.Columns.Clear(); foreach (var col in columns) { var column = listView.Columns.Add(col.Name, col.Width, col.Align); column.Tag = col.Tag; // 用于排序时判断数据类型 } // 创建示例数据 var items = new[] { CreateListViewItem("001", "用户管理", "系统用户管理模块", DateTime.Now.AddDays(-5), "启用"), CreateListViewItem("002", "权限控制", "角色权限管理功能", DateTime.Now.AddDays(-3), "启用"), CreateListViewItem("003", "数据备份", "定期数据备份服务", DateTime.Now.AddDays(-1), "禁用"), CreateListViewItem("004", "日志管理", "系统操作日志记录", DateTime.Now, "启用"), CreateListViewItem("005", "报表统计", "业务数据统计分析", DateTime.Now.AddDays(-7), "维护中") }; // 批量添加项目 listView.BeginUpdate(); // 开始批量更新,提高性能 listView.Items.Clear(); listView.Items.AddRange(items); listView.EndUpdate(); // 结束批量更新 // 自动调整列宽 AutoResizeColumns(); } private ListViewItem CreateListViewItem(string id, string name, string desc, DateTime createTime, string status) { var item = new ListViewItem(id); item.SubItems.Add(name); item.SubItems.Add(desc); item.SubItems.Add(createTime.ToString("yyyy-MM-dd HH:mm")); item.SubItems.Add(status); // 根据状态设置颜色 switch (status) { case "启用": item.ForeColor = Color.Green; break; case "禁用": item.ForeColor = Color.Red; break; case "维护中": item.ForeColor = Color.Orange; break; } // 存储完整数据到Tag中,便于后续操作 item.Tag = new ItemData { ID = id, Name = name, Description = desc, CreateTime = createTime, Status = status }; return item; } private void AutoResizeColumns() { // 自动调整列宽 foreach (ColumnHeader column in listView.Columns) { column.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent); column.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize); } } private void BindEvents() { // 按钮事件 btnAdd.Click += BtnAdd_Click; btnEdit.Click += BtnEdit_Click; btnDelete.Click += BtnDelete_Click; // 搜索框事件 txtSearch.TextChanged += TxtSearch_TextChanged; // ListView事件 listView.ColumnClick += ListView_ColumnClick; listView.SelectedIndexChanged += ListView_SelectedIndexChanged; listView.DoubleClick += ListView_DoubleClick; listView.KeyDown += ListView_KeyDown; // 右键菜单 SetupContextMenu(); } private void SetupContextMenu() { var contextMenu = new ContextMenuStrip(); contextMenu.Items.Add("编辑", null, (s, e) => EditSelectedItem()); contextMenu.Items.Add("删除", null, (s, e) => DeleteSelectedItem()); contextMenu.Items.Add(new ToolStripSeparator()); contextMenu.Items.Add("刷新", null, (s, e) => RefreshData()); listView.ContextMenuStrip = contextMenu; } #region 事件处理 private void BtnAdd_Click(object sender, EventArgs e) { // 添加新项目的逻辑 var newId = (listView.Items.Count + 1).ToString("000"); var newItem = CreateListViewItem(newId, "新项目", "新建的项目", DateTime.Now, "启用"); listView.Items.Add(newItem); newItem.Selected = true; newItem.EnsureVisible(); } private void BtnEdit_Click(object sender, EventArgs e) { EditSelectedItem(); } private void BtnDelete_Click(object sender, EventArgs e) { DeleteSelectedItem(); } private void TxtSearch_TextChanged(object sender, EventArgs e) { FilterItems(txtSearch.Text); } private void ListView_ColumnClick(object sender, ColumnClickEventArgs e) { // 列点击排序 var sorter = listView.ListViewItemSorter as ListViewItemComparer; if (sorter != null) { if (sorter.Column == e.Column) { sorter.Order = sorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending; } else { sorter.Column = e.Column; sorter.Order = SortOrder.Ascending; } listView.Sort(); } } private void ListView_SelectedIndexChanged(object sender, EventArgs e) { // 更新按钮状态 bool hasSelection = listView.SelectedItems.Count > 0; btnEdit.Enabled = hasSelection; btnDelete.Enabled = hasSelection; } private void ListView_DoubleClick(object sender, EventArgs e) { if (listView.SelectedItems.Count > 0) { EditSelectedItem(); } } private void ListView_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Delete) { DeleteSelectedItem(); } else if (e.KeyCode == Keys.F5) { RefreshData(); } } #endregion #region 辅助方法 private void EditSelectedItem() { if (listView.SelectedItems.Count == 0) return; var selectedItem = listView.SelectedItems[0]; var itemData = selectedItem.Tag as ItemData; // 这里可以打开编辑对话框 MessageBox.Show($"编辑项目: {itemData?.Name}", "编辑", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void DeleteSelectedItem() { if (listView.SelectedItems.Count == 0) return; var result = MessageBox.Show("确定要删除选中的项目吗?", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { foreach (ListViewItem item in listView.SelectedItems) { listView.Items.Remove(item); } } } private void FilterItems(string searchText) { if (string.IsNullOrWhiteSpace(searchText)) { // 显示所有项目 foreach (ListViewItem item in listView.Items) { item.Tag = ((ItemData)item.Tag); // 保持原有Tag } return; } // 简单的文本过滤 listView.BeginUpdate(); foreach (ListViewItem item in listView.Items) { bool isMatch = item.SubItems.Cast<ListViewItem.ListViewSubItem>() .Any(subItem => subItem.Text.Contains(searchText, StringComparison.OrdinalIgnoreCase)); // 这里可以实现隐藏/显示逻辑 // 由于ListView没有直接的隐藏功能,要不就重建Items集合 } listView.EndUpdate(); } private void RefreshData() { // 刷新数据 AddColumnsAndItems(); } #endregion } // 数据模型 public class ItemData { public string ID { get; set; } public string Name { get; set; } public string Description { get; set; } public DateTime CreateTime { get; set; } public string Status { get; set; } } // ListView排序比较器 public class ListViewItemComparer : System.Collections.IComparer { public int Column { get; set; } public SortOrder Order { get; set; } = SortOrder.Ascending; public ListViewItemComparer(int column) { Column = column; } public int Compare(object x, object y) { var item1 = x as ListViewItem; var item2 = y as ListViewItem; if (item1 == null || item2 == null) return 0; string text1 = item1.SubItems[Column].Text; string text2 = item2.SubItems[Column].Text; int result = 0; // 根据列类型进行不同的比较 var column = item1.ListView.Columns[Column]; if (column.Tag?.ToString() == "datetime") { if (DateTime.TryParse(text1, out DateTime date1) && DateTime.TryParse(text2, out DateTime date2)) { result = DateTime.Compare(date1, date2); } } else if (int.TryParse(text1, out int num1) && int.TryParse(text2, out int num2)) { result = num1.CompareTo(num2); } else { result = string.Compare(text1, text2, StringComparison.OrdinalIgnoreCase); } return Order == SortOrder.Descending ? -result : result; } } }

image.png

⚠️ 避坑指南

  • Width设置为-2可自动调整列宽
  • 批量添加比逐个添加性能更优

⚡ 实战技巧3:智能事件处理

用户交互是ListView的核心价值,以下是企业级事件处理方案:

C#
private void SetupEventHandlers() { // 选择变化事件 listView.ItemSelectionChanged += (sender, e) => { if (e.IsSelected) { var selectedItem = e.Item; // 获取选中项的详细信息 var id = selectedItem.Text; var name = selectedItem.SubItems[1].Text; UpdateDetailsPanel(id, name); } }; // 双击事件处理 listView.ItemActivate += (sender, e) => { if (listView.SelectedItems.Count > 0) { var item = listView.SelectedItems[0]; EditItem(item); } }; } private void UpdateDetailsPanel(string id, string name) { // 更新详情面板的逻辑 lblDetails.Text = $"当前选中:{name} (ID: {id})"; }

🎨 实战技巧4:自定义排序器

默认排序往往无法满足业务需求,自定义排序器是进阶必备技能:

C#
public class SmartListViewComparer : IComparer { private int columnIndex; private SortOrder sortOrder; public SmartListViewComparer(int column, SortOrder order = SortOrder.Ascending) { columnIndex = column; sortOrder = order; } public int Compare(object x, object y) { var itemX = (ListViewItem)x; var itemY = (ListViewItem)y; var textX = itemX.SubItems[columnIndex].Text; var textY = itemY.SubItems[columnIndex].Text; // 智能比较:数字按数值比较,文本按字母比较 int result = 0; if (int.TryParse(textX, out int numX) && int.TryParse(textY, out int numY)) { result = numX.CompareTo(numY); } else { result = string.Compare(textX, textY, StringComparison.OrdinalIgnoreCase); } return sortOrder == SortOrder.Ascending ? result : -result; } } // 应用自定义排序 listView.ListViewItemSorter = new SmartListViewComparer(0);

⚡ 实战技巧5:虚拟模式性能优化

处理大数据量时,虚拟模式是性能救星:

C#
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace AppBasicListView { public partial class Form3 : Form { private ListView listView; private Label statusLabel; private Button loadDataButton; private Button clearButton; private TextBox searchTextBox; private Button searchButton; private ProgressBar progressBar; private List<DataModel> virtualData = new List<DataModel>(); private List<DataModel> filteredData = new List<DataModel>(); private bool isFiltered = false; public Form3() { InitializeComponent(); InitializeControls(); } private void InitializeControls() { this.Size = new Size(900, 650); this.Text = "WinForm 虚拟模式大数据演示"; this.StartPosition = FormStartPosition.CenterScreen; // 创建控件 CreateControls(); EnableVirtualMode(); } private void CreateControls() { // 顶部控制面板 var topPanel = new Panel { Dock = DockStyle.Top, Height = 80, Padding = new Padding(10) }; loadDataButton = new Button { Text = "加载大数据集 (10万条)", Size = new Size(150, 30), Location = new Point(10, 10) }; loadDataButton.Click += LoadDataButton_Click; clearButton = new Button { Text = "清空数据", Size = new Size(80, 30), Location = new Point(170, 10) }; clearButton.Click += ClearButton_Click; // 搜索功能 var searchLabel = new Label { Text = "搜索:", Size = new Size(40, 30), Location = new Point(270, 15), TextAlign = ContentAlignment.MiddleLeft }; searchTextBox = new TextBox { Size = new Size(120, 25), Location = new Point(315, 12) }; searchTextBox.KeyPress += SearchTextBox_KeyPress; searchButton = new Button { Text = "搜索", Size = new Size(60, 25), Location = new Point(445, 12) }; searchButton.Click += SearchButton_Click; var resetSearchButton = new Button { Text = "重置", Size = new Size(60, 25), Location = new Point(515, 12) }; resetSearchButton.Click += ResetSearchButton_Click; // 进度条 progressBar = new ProgressBar { Size = new Size(200, 20), Location = new Point(10, 45), Visible = false }; // 状态标签 statusLabel = new Label { Text = "就绪 - 点击\"加载大数据集\"开始演示", Size = new Size(400, 20), Location = new Point(220, 47), ForeColor = Color.Blue }; topPanel.Controls.AddRange(new Control[] { loadDataButton, clearButton, searchLabel, searchTextBox, searchButton, resetSearchButton, progressBar, statusLabel }); // ListView 设置 listView = new ListView { Dock = DockStyle.Fill, View = View.Details, FullRowSelect = true, GridLines = true, VirtualMode = false // 初始状态 }; // 添加列 listView.Columns.Add("ID", 80, HorizontalAlignment.Right); listView.Columns.Add("名称", 200, HorizontalAlignment.Left); listView.Columns.Add("描述", 300, HorizontalAlignment.Left); listView.Columns.Add("创建时间", 150, HorizontalAlignment.Left); listView.Columns.Add("状态", 100, HorizontalAlignment.Center); this.Controls.Add(listView); this.Controls.Add(topPanel); } private void EnableVirtualMode() { listView.VirtualMode = true; listView.VirtualListSize = 0; // 虚拟项检索事件 listView.RetrieveVirtualItem += ListView_RetrieveVirtualItem; // 搜索虚拟项事件(用于查找功能) listView.SearchForVirtualItem += ListView_SearchForVirtualItem; // 缓存虚拟项事件(性能优化) listView.CacheVirtualItems += ListView_CacheVirtualItems; } private void ListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) { try { var dataSource = isFiltered ? filteredData : virtualData; if (e.ItemIndex >= 0 && e.ItemIndex < dataSource.Count) { var data = dataSource[e.ItemIndex]; var item = new ListViewItem(data.Id.ToString()); item.SubItems.Add(data.Name); item.SubItems.Add(data.Description); item.SubItems.Add(data.CreatedTime.ToString("yyyy-MM-dd HH:mm:ss")); item.SubItems.Add(data.Status); // 根据状态设置颜色 if (data.Status == "活跃") item.BackColor = Color.LightGreen; else if (data.Status == "警告") item.BackColor = Color.LightYellow; else if (data.Status == "错误") item.BackColor = Color.LightCoral; item.Tag = data; // 保存数据引用 e.Item = item; } } catch (Exception ex) { // 异常处理 var errorItem = new ListViewItem("ERROR"); errorItem.SubItems.Add(ex.Message); e.Item = errorItem; } } private void ListView_SearchForVirtualItem(object sender, SearchForVirtualItemEventArgs e) { var dataSource = isFiltered ? filteredData : virtualData; for (int i = e.StartIndex; i < dataSource.Count; i++) { if (dataSource[i].Name.StartsWith(e.Text, StringComparison.OrdinalIgnoreCase)) { e.Index = i; return; } } e.Index = -1; // 未找到 } private void ListView_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e) { // 这里可以实现数据预缓存逻辑,提高性能 // 例如:预加载 e.StartIndex 到 e.EndIndex 范围的数据 statusLabel.Text = $"缓存项目: {e.StartIndex} - {e.EndIndex}"; } private async void LoadDataButton_Click(object sender, EventArgs e) { loadDataButton.Enabled = false; progressBar.Visible = true; progressBar.Value = 0; var stopwatch = Stopwatch.StartNew(); statusLabel.Text = "正在生成大数据集..."; try { // 使用后台任务生成数据 await Task.Run(() => InitializeLargeDataSet()); stopwatch.Stop(); // 更新虚拟列表大小 listView.VirtualListSize = virtualData.Count; statusLabel.Text = $"✅ 成功加载 {virtualData.Count:N0} 条记录,耗时: {stopwatch.ElapsedMilliseconds} 毫秒"; statusLabel.ForeColor = Color.Green; } catch (Exception ex) { statusLabel.Text = $"❌ 加载失败: {ex.Message}"; statusLabel.ForeColor = Color.Red; } finally { loadDataButton.Enabled = true; progressBar.Visible = false; } } private void InitializeLargeDataSet() { virtualData.Clear(); var random = new Random(); var statuses = new[] { "活跃", "非活跃", "警告", "错误" }; var baseTime = DateTime.Now.AddDays(-365); // 生成10万条测试数据 for (int i = 0; i < 100000; i++) { virtualData.Add(new DataModel { Id = i + 1, Name = $"数据项目 {i + 1:D6}", Description = $"这是第 {i + 1} 个数据项的详细描述信息", CreatedTime = baseTime.AddMinutes(random.Next(0, 525600)), // 随机时间 Status = statuses[random.Next(statuses.Length)] }); // 更新进度(每1000条更新一次,避免UI卡顿) if (i % 1000 == 0) { var progress = (int)((double)i / 100000 * 100); this.Invoke(new Action(() => { progressBar.Value = progress; statusLabel.Text = $"正在生成数据... {i + 1:N0} / 100,000"; })); } } } private void ClearButton_Click(object sender, EventArgs e) { virtualData.Clear(); filteredData.Clear(); isFiltered = false; listView.VirtualListSize = 0; searchTextBox.Clear(); statusLabel.Text = "数据已清空"; statusLabel.ForeColor = Color.Blue; } private void SearchButton_Click(object sender, EventArgs e) { PerformSearch(); } private void SearchTextBox_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)Keys.Enter) { PerformSearch(); e.Handled = true; } } private void PerformSearch() { var searchText = searchTextBox.Text.Trim(); if (string.IsNullOrEmpty(searchText)) { ResetSearch(); return; } var stopwatch = Stopwatch.StartNew(); statusLabel.Text = "正在搜索..."; // 执行搜索(这里演示简单的名称搜索) filteredData = virtualData.Where(x => x.Name.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0 || x.Description.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0) .ToList(); isFiltered = true; listView.VirtualListSize = filteredData.Count; stopwatch.Stop(); statusLabel.Text = $"🔍 找到 {filteredData.Count:N0} 条匹配记录,耗时: {stopwatch.ElapsedMilliseconds} 毫秒"; statusLabel.ForeColor = Color.DarkGreen; } private void ResetSearchButton_Click(object sender, EventArgs e) { ResetSearch(); } private void ResetSearch() { searchTextBox.Clear(); filteredData.Clear(); isFiltered = false; listView.VirtualListSize = virtualData.Count; statusLabel.Text = $"显示全部 {virtualData.Count:N0} 条记录"; statusLabel.ForeColor = Color.Blue; } } // 数据模型 public class DataModel { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public DateTime CreatedTime { get; set; } public string Status { get; set; } } }

image.png

🚀 性能提升:虚拟模式可将大数据集的加载时间从秒级降至毫秒级!

🎯 总结与实战建议

通过本文的深度剖析,我们掌握了ListView的三个核心要点:

  1. 灵活配置:合理选择视图模式和属性配置,打造专业界面
  2. 高效数据处理:掌握批量操作和虚拟模式,提升应用性能
  3. 智能交互设计:通过事件处理和自定义排序,优化用户体验

ListView不仅仅是一个简单的列表控件,它是构建企业级WinForms应用的重要基石。掌握这些进阶技巧,你的C#开发技能将更上一层楼!


💬 互动讨论

你在ListView开发中遇到过哪些性能瓶颈?在虚拟模式和自定义绘制方面有什么实战经验?欢迎在评论区分享你的见解!

🔖 收藏建议:建议将本文中的代码模板保存到你的代码库中,特别是虚拟模式和自定义排序器的实现,这些都是实际项目中的高频需求。

觉得内容对你有帮助?点赞+转发给更多C#开发同行,让大家一起提升技术水平!

#C#开发 #WinForms #ListView #编程技巧 #性能优化

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!