C#ListView数据绑定组件
一、ListView组件
1.1 常用属性
1.View 设置显示模式
- Details(详细视图):表格形式展示多列数据,支持自定义列宽、对齐方式。
- List(列表视图):单列垂直排列,适合简单选项。
- LargeIcon/SmallIcon(大/小图标):以图标形式展示,支持自定义图标集。
- Tile(平铺视图):类似卡片布局,展示图标和文本。
listView1.View = View.Details;
2.Columns 详细信息视图中显示的列集合,也就是表头
listView1.Columns.Add("姓名", 100);//第一个参数是列名,第二个参数是Width宽度
listView1.Columns.Add("年龄", 80);//按照顺序来加列名
3.Items 列表中所有项的集合,也就是行记录集合
- ListViewItem : Items集合包含的是一个一个Item对象
- Text: 第一列的文本
- SubItems: 除第一列的其他列的集合
ListViewItem item = new ListViewItem("张三");//增加一个表名
item.SubItems.Add("25");
listView1.Items.Add(item);
4.FullRowSelect是否整行选择(仅Details视图)
listView1.FullRowSelect = true;
5.GridLines 是否显示网格线(仅Details视图)
listView1.GridLines = true;
6.MultiSelect 是否允许多选
listView1.MultiSelect = true;
7.CheckBoxes是否显示复选框
listView1.CheckBoxes = true;
8.SelectedItems 获取当前选中的项目集合
listView1.SelectedItems[0].SubItems[1].Text//获取集合中第二个元素文本
//还可以判断是否选中
listView1.SelectedItems.Count == 0//如果集合的数量为0,表示没有选中
9.SelectedIndices 获取当前选中的项目的索引集合
//根据索引获取选中项的内容
foreach (int index in listBox1.SelectedIndices)
{
object item = listBox1.Items[index];
Console.WriteLine($"索引 {index}: {item}");
}
10.Sorting 设置排序方式(None, Ascending(升序), Descending(降序))
// 初始化比较器
ListViewItemComparer itemComparer = new ListViewItemComparer();
// 设置比较器
listView1.ListViewItemSorter = itemComparer;
// 使用ColumnClick点击事件触发排序
listView1.Sort();
1.2 常用方法
1.BeginUpdate()/EndUpdate():批量更新时提高性能
// 开始批量更新 → 暂停界面刷新
listView1.BeginUpdate();
// 模拟添加10000条数据
for (int i = 1; i <= 10000; i++)
{
ListViewItem item = new ListViewItem($"编号 {i}");
item.SubItems.Add($"数据 {i}");
listView1.Items.Add(item);
}
// 结束批量更新 → 一次性刷新界面
listView1.EndUpdate();
2.EnsureVisible():确保指定项可见,始终显示在可见
// 让第99项显示出来(索引从0开始)
int targetIndex = 99;
listView1.Items[targetIndex].EnsureVisible();//类似于Excel的视图冻结
3.Sort():对列表进行排序
listView1.Sort();//升序排序
4.Clear():清除所有项目和列
listView1.Clear();
二、基本使用
2.1 添加列(Details视图)
listView2.View = View.Details;
listView2.Columns.Add("编号", 100);
listView2.Columns.Add("姓名", 100);
listView2.Columns.Add("年龄", 80);
listView2.Columns.Add("部门", 150);
2.2 添加项目
int idx = 1;
private void btnAdd_Click(object sender, EventArgs e)
{
// 模拟数据
ListViewItem item = new ListViewItem(idx.ToString());
item.SubItems.Add("zhansan");
item.SubItems.Add(21.ToString());
item.SubItems.Add("研发部");
listView2.Items.Add(item);
idx++;
}
2.3 批量增加 (使用BeginUpdate()/EndUpdate()减少重绘)
private void btnBatchAdd_Click(object sender, EventArgs e)
{
listView2.BeginUpdate();
//添加5000行数据
for (int i = 0; i < 5000; i++)
{
ListViewItem item = new ListViewItem((idx++).ToString());
item.SubItems.Add("zhansan"+idx);
item.SubItems.Add(21.ToString());
item.SubItems.Add("研发部"+idx);
listView2.Items.Add(item);
}
listView2.EndUpdate();
}
- 对于极大列表(>10,000项),考虑使用虚拟模式
- 虚拟模式是一种优化技术,允许ListView仅加载和显示当前可见项,而不是一次性加载所有数据,特别适合处理大数据集(10,000+项)。
private void btnBatchAdd_Click(object sender, EventArgs e)
{
listView2.BeginUpdate();
listView2.VirtualMode = true;
listView2.VirtualListSize = 100000; // 设置虚拟列表的大小
// 处理检索虚拟项目事件
listView2.RetrieveVirtualItem += (obj, ev) =>
{
ev.Item = new ListViewItem((idx++).ToString());
ev.Item.SubItems.Add("zhansan" + idx);
ev.Item.SubItems.Add(21.ToString());
ev.Item.SubItems.Add("研发部" + idx);
};
listView2.EndUpdate();
}
2.4 修改项目
private void btnEdit_Click(object sender, EventArgs e)
{
int index = Convert.ToInt32(this.mudIndex.Value);//基于下标
listView2.Items[index].SubItems[1].Text = "lisi";
listView2.Items[index].SubItems[2].Text = "22";
listView2.Items[index].SubItems[3].Text = "市场部";
//基于复选框 || 选择项
var checkItem = listView1.CheckedItems[0]; // 获取复选框第一行
var selectItem = listView1.SelectedItems[0]; // 获取选择项第一行
checkItem.SubItems[1].Text = "lisi";
checkItem.SubItems[2].Text = "22";
checkItem.SubItems[3].Text = "市场部";
}
2.5 删除项目
//基于选择项删除 listView1.Items.Remove(listView1.SelectedItems[0]);
//基于复选框删除
listView1.Items.Remove(listView1.CheckedItems[0]);
2.6 添加图标
private void uiButton1_Click(object sender, EventArgs e)
{
listView1.SmallImageList = SmallimageList;
listView1.LargeImageList = BigimageList;
listView2.BeginUpdate();
for (int i = 0; i < 100; i++)
{
int index = i % SmallimageList.Images.Count;
ListViewItem item = new ListViewItem((id++).ToString(), index);
item.SubItems.Add("zhansan" + id);
item.SubItems.Add("123456");
item.SubItems.Add(id % 2 == 0?"可用":"禁用") ;
listView1.Items.Add(item);
}
listView2.EndUpdate();
}
注意事项:
- 添加
ImageList组件 - 往
ImageList组件里面的Images属性里面添加图标,设置ImageSize大小 - 代码绑定ListView的LargeImageList/SmallImageList,也可以手动设置
- 尽量大小图标数量保持一致
2.7 排序
点击列头,按照指定列进行排序
第一步 编写列头比较器类
/// <summary>
/// 自定义 ListViewItem 比较器
/// </summary>
public class ListViewItemComparer : IComparer
{
/// <summary>
/// 指定按照哪一列进行排序
/// </summary>
private int _columnToSort;
/// <summary>
/// 指定排序方式
/// </summary>
private System.Windows.Forms.SortOrder _orderOfSort;
/// <summary>
/// 声明CaseInsensitiveComparer对象
/// </summary>
private System.Collections.CaseInsensitiveComparer _comparer;
public ListViewItemComparer() {
//默认按第一列排序
_columnToSort = 0;
//默认不排序
_orderOfSort = System.Windows.Forms.SortOrder.None;
//初始化比较器
_comparer = new System.Collections.CaseInsensitiveComparer();
}
/// <summary>
/// 重写 Compare 方法
/// </summary>
/// <param name="x">比较的第一个对象</param>
/// <param name="y">比较的第二个对象</param>
/// <returns>比较结果: 相等返回0, x大于y返回1,x小于y返回-1</returns>
public int Compare(object x, object y)
{
int compareResult;
System.Windows.Forms.ListViewItem listviewX, listviewY;
//将object转换为ListViewItem
listviewX = (System.Windows.Forms.ListViewItem)x;
listviewY = (System.Windows.Forms.ListViewItem)y;
string xText = listviewX.SubItems[_columnToSort].Text;
string yText = listviewY.SubItems[_columnToSort].Text;
//比较
//如果全是数字
if (double.TryParse(xText, out double xInt) && double.TryParse(yText, out double yInt))
{
//比较数字
compareResult = xInt.CompareTo(yInt);
}
else
//比较字符串
{
compareResult = xText.CompareTo(yText);
}
//根据比较结果和排序方式返回结果
if (_orderOfSort == System.Windows.Forms.SortOrder.Ascending)
{
//升序
return compareResult;
}
else if (_orderOfSort == System.Windows.Forms.SortOrder.Descending)
{
//降序
return (-compareResult);
}
else
{
//相等返回0
return 0;
}
}
/// <summary>
/// 获取或设置排序列
/// </summary>
public int ColumnToSort {
get
{
return _columnToSort;
}
set
{
_columnToSort = value;
}
}
/// <summary>
/// 获取或设置排序方式
/// </summary>
public System.Windows.Forms.SortOrder OrderOfSort
{
get
{
return _orderOfSort;
}
set
{
_orderOfSort = value;
}
}
}
第二步 给ListView添加一个ColumnClick事件
// 初始化比较器
private ListViewItemComparer comparer = new ListViewItemComparer();
private void listView2_ColumnClick(object sender, ColumnClickEventArgs e)
{
if (e.Column == comparer.ColumnToSort)
{
if (comparer.OrderOfSort == SortOrder.Ascending)
{
comparer.OrderOfSort = SortOrder.Descending;
}
else
{
comparer.OrderOfSort = SortOrder.Ascending;
}
}
else
{
comparer.ColumnToSort = e.Column;
comparer.OrderOfSort = SortOrder.Ascending;
}
this.listView2.Sort();
}
第三步 给ListView设置ListViewItemSorter比较器
//设置比较器
listView2.ListViewItemSorter = comparer;
三、习题讲解
题目: 使用ListView完成用户CURD操作, 效果图如下:

思路:
根据题目要求,需要实现在修改用户的时候,将选中的用户信息显示在添加窗口上,并且还要把修改后的数据重新给到ListView组件上;这里可以用到前面学过的事件的发布-订阅机制来实现
事件机制:发布者:发布指令和触发事件的方法,订阅者:触发事件,响应指令
首先需要确定谁是谁是事件的发布者,谁是订阅者,AddForm窗口需要获取ListView上面的数据,所有它是发布者,Form1需要把ListView的数据传给AddForm,所有Form1是订阅者。
实现添加功能:
AddForm窗口:
定义事件参数类:
public class AddItemEventArgs:EventArgs
{
public string Name { get; set; }
public string Password { get; set; }
public string State { get; set; }
}
定义事件
public event EventHandler<AddItemEventArgs> AddEvent;
定义触发事件
private void Save_btn_Click(object sender, EventArgs e)
{
string name = NameText.Text;
string password =PasswordText.Text;
string state = "";
if (StateRbtn.Checked)
{
state = StateRbtn.Text;
}
else if (StateRbtn2.Checked)
{
state= StateRbtn2.Text;
}
//触发事件
AddEvent?.Invoke(this, new AddItemEventArgs() {
Name= name,
Password= password,
State= state
});
MessageBox.Show("添加成功");
Close();
}
Form1窗口(主窗口):
事件订阅者:
设置列头
private void AddColumns()
{
listView1.Columns.Clear();
listView1.View = View.Details;
listView1.Columns.Add("编号", 120);
listView1.Columns.Add("用户名", 170);
listView1.Columns.Add("密码", 170);
listView1.Columns.Add("状态", 170);
}
窗体初始化
private void Form1_Load(object sender, EventArgs e)
{
AddColumns();
//设置比较器
listView1.ListViewItemSorter = comparer;
//设置小图标和大图标的列表
//listView1.SmallImageList = SmallimageList;
//listView1.LargeImageList = BigimageList;
}
点击按钮订阅事件
private int id = 1;
private void Add_btn_Click(object sender, EventArgs e)
{
//显示添加窗体
AddForm addForm = new AddForm();
//订阅事件
addForm.AddEvent += (target, ev) =>
{
//把数据添加到ListView中
ListViewItem item = new ListViewItem(id.ToString(),id% SmallimageList.Images.Count);
//添加其他列的值
item.SubItems.Add(ev.Name);
item.SubItems.Add(ev.Password.ToString());
item.SubItems.Add(ev.State);
//把ListViewItem添加到Items属性
listView1.Items.Add(item);
id++;
};
addForm.ShowDialog();
}
实现修改用户功能:(同理)
Update:
public partial class Update : UIForm
{
//定义事件
public event EventHandler<AddItemEventArgs> UpdateEvent;
public Update()
{
InitializeComponent();
}
public AddItemEventArgs args;
public Update(AddItemEventArgs addItem)
{
InitializeComponent();
args = addItem;
}
#region 加载修改窗体
private void Update_Load(object sender, EventArgs e)
{
NameText.Text = args.Name;
PasswordText.Text = args.Password;
if (args.State == "可用")
{
StateRbtn.Checked = true;
}
else
{
StateRbtn2.Checked = true;
}
}
#endregion
//按钮绑定触发事件
private void Save_btn_Click(object sender, EventArgs e)
{
string name = NameText.Text;
string password = PasswordText.Text;
string state = string.Empty;
if (StateRbtn.Checked)
{
state = StateRbtn.Text;
}
else if (StateRbtn2.Checked)
{
state = StateRbtn2.Text;
}
if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(password) || string.IsNullOrWhiteSpace(state))
{
MessageBox.Show("请填写或者选择!");
}
else
{
UpdateEvent?.Invoke(this, new AddItemEventArgs()
{
Name = name,
Password = password,
State = StateRbtn.Checked ? "可用" : "禁用"
});
MessageBox.Show("温馨提示!", "修改成功!");
Close();
}
}
}
Form1中:
private void Update_btn_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0 && listView1.CheckedItems.Count==0)
{
MessageBox.Show("请选择数据!");
}
else if(listView1.SelectedItems.Count != 0)//修改选择项
{
AddItemEventArgs eventArgs = new AddItemEventArgs()
{
Name = listView1.CheckedItems[0].SubItems[1].Text,
Password = listView1.CheckedItems[0].SubItems[2].Text,
State = listView1.CheckedItems[0].SubItems[3].Text
};
Update update = new Update(eventArgs);
update.UpdateEvent += (obj, ev) =>
{
listView1.CheckedItems[0].SubItems[1].Text = ev.Name;
listView1.CheckedItems[0].SubItems[2].Text = ev.Password;
listView1.CheckedItems[0].SubItems[3].Text = ev.State;
};
update.ShowDialog();
}
}
实现删除功能
private void Clear_btn_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0 && listView1.CheckedItems.Count==0)
{
MessageBox.Show("请先选择数据!");
}
else if (listView1.SelectedItems.Count != 0) // 只能单删
{
UIMessageBox.ShowMessageDialog2("温馨提示", $"用户信息:{listView1.SelectedItems[0].SubItems[1].Text} 删除成功!", UINotifierType.WARNING);
listView1.Items.Remove(listView1.SelectedItems[0]);
}
else if (listView1.CheckedItems.Count != 0) // 多删
{
listView1.BeginUpdate();
StringBuilder sb = new StringBuilder();
sb.AppendLine();
foreach (ListViewItem item in listView1.CheckedItems)
{
for (int i = 0; i < listView1.Columns.Count; i++)
{
sb.Append(item.SubItems[i].Text + ", ");
}
sb.AppendLine();
}
DialogResult result = MessageBox.Show($"确定要删除如下选项:{sb.ToString()}", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (result == DialogResult.Yes)
{
foreach (ListViewItem item in listView1.CheckedItems)
{
listView1.Items.Remove(item);
}
}
listView1.EndUpdate();
}
}
四、总结
ListView有不同视图展示数据,但它的所有列都是文本Text属性,比较单一,不能实现多类型,如果要实现多种类型的,推荐使用DataGridView组件。

浙公网安备 33010602011771号