当前博文未提及该问题,以下是基于C知道的知识内容为您回答
在C# WinForms开发中,`ListView`控件是用于展示列表数据的常用控件。实现新增和删除行数据是其核心交互功能之一。下面将详细讲解这两种操作的实现方法、关键属性、事件处理以及最佳实践。
## 1. ListView基础结构与数据模型
### 1.1 ListView的视图模式与结构
`ListView`控件支持多种视图模式,最常用于表格形式的是`Details`视图:
| 视图模式 | 枚举值 | 适用场景 |
|---------|--------|---------|
| 大图标 | `LargeIcon` | 文件资源管理器图标视图 |
| 小图标 | `SmallIcon` | 紧凑图标显示 |
| 列表 | `List` | 简单列表 |
| 详细信息 | `Details` | **表格数据展示(最常用)** |
| 平铺 | `Tile` | Windows XP风格平铺 |
要使用表格形式,必须设置以下属性:
```csharp
// 设置ListView为详细信息视图 [ref_4]
listView1.View = View.Details;
// 添加列(表头)
listView1.Columns.Add("ID", 80, HorizontalAlignment.Left);
listView1.Columns.Add("姓名", 100, HorizontalAlignment.Left);
listView1.Columns.Add("年龄", 60, HorizontalAlignment.Center);
listView1.Columns.Add("邮箱", 180, HorizontalAlignment.Left);
// 启用整行选择和网格线 [ref_6]
listView1.FullRowSelect = true; // 点击时选中整行
listView1.GridLines = true; // 显示网格线
listView1.MultiSelect = false; // 禁止多选(根据需求设置)
```
### 1.2 ListViewItem与SubItems的数据结构
`ListView`的数据由`ListViewItem`对象组成,每个项可以包含多个子项:
```csharp
// 创建ListViewItem(主项对应第一列)
ListViewItem item = new ListViewItem("001"); // ID列
// 添加子项(对应后续列)
item.SubItems.Add("张三"); // 姓名列
item.SubItems.Add("25"); // 年龄列
item.SubItems.Add("zhangsan@example.com"); // 邮箱列
// 可选:设置行颜色、字体等
item.BackColor = Color.LightYellow;
item.Font = new Font("微软雅黑", 10);
// 将项添加到ListView
listView1.Items.Add(item);
```
## 2. 新增行数据的完整实现
### 2.1 基础新增方法
以下是完整的添加行数据的示例代码:
```csharp
using System;
using System.Drawing;
using System.Windows.Forms;
namespace ListViewDemo
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
InitializeListView();
}
private void InitializeListView()
{
// 1. 设置视图和列 [ref_4]
listViewData.View = View.Details;
listViewData.FullRowSelect = true;
listViewData.GridLines = true;
// 2. 添加列头
listViewData.Columns.Add("序号", 60, HorizontalAlignment.Center);
listViewData.Columns.Add("产品名称", 150, HorizontalAlignment.Left);
listViewData.Columns.Add("单价", 80, HorizontalAlignment.Right);
listViewData.Columns.Add("库存", 70, HorizontalAlignment.Center);
listViewData.Columns.Add("入库日期", 120, HorizontalAlignment.Center);
// 3. 添加示例数据
AddSampleData();
}
private void AddSampleData()
{
// 示例数据
string[,] sampleProducts = {
{"001", "笔记本电脑", "5999.00", "45", "2024-01-15"},
{"002", "无线鼠标", "89.50", "120", "2024-02-10"},
{"003", "机械键盘", "399.00", "78", "2024-03-05"}
};
for (int i = 0; i < sampleProducts.GetLength(0); i++)
{
AddRow(
sampleProducts[i, 0], // 序号
sampleProducts[i, 1], // 产品名称
sampleProducts[i, 2], // 单价
sampleProducts[i, 3], // 库存
sampleProducts[i, 4] // 入库日期
);
}
}
// 新增行数据的核心方法
public void AddRow(string id, string productName, string price, string stock, string date)
{
// 创建新的ListViewItem
ListViewItem newItem = new ListViewItem(id);
// 添加子项 [ref_3]
newItem.SubItems.Add(productName);
newItem.SubItems.Add(price);
newItem.SubItems.Add(stock);
newItem.SubItems.Add(date);
// 根据库存量设置行颜色
int stockNum;
if (int.TryParse(stock, out stockNum))
{
if (stockNum < 10)
newItem.BackColor = Color.LightPink; // 库存不足
else if (stockNum > 100)
newItem.BackColor = Color.LightGreen; // 库存充足
}
// 添加到ListView [ref_2]
listViewData.Items.Add(newItem);
// 可选:自动滚动到最后一行
newItem.EnsureVisible();
// 更新状态栏
UpdateStatus($"成功添加产品: {productName}");
}
// 通过按钮添加新行(UI交互)
private void btnAdd_Click(object sender, EventArgs e)
{
// 在实际应用中,这里可以打开一个对话框获取用户输入
// 此处使用模拟数据
int nextId = listViewData.Items.Count + 1;
AddRow(
nextId.ToString("D3"), // 格式化为三位数
txtProductName.Text,
txtPrice.Text,
txtStock.Text,
DateTime.Now.ToString("yyyy-MM-dd")
);
// 清空输入框
ClearInputFields();
}
private void ClearInputFields()
{
txtProductName.Clear();
txtPrice.Clear();
txtStock.Clear();
}
private void UpdateStatus(string message)
{
lblStatus.Text = $"状态: {message} (总计: {listViewData.Items.Count} 条记录)";
}
}
}
```
### 2.2 高级新增功能:数据验证与批量添加
```csharp
using System.Text.RegularExpressions;
public partial class MainForm : Form
{
// 批量添加数据
public void AddRowsBatch(List<Product> products)
{
// 开始更新,避免频繁刷新UI
listViewData.BeginUpdate();
try
{
foreach (Product product in products)
{
if (ValidateProduct(product))
{
ListViewItem item = new ListViewItem(product.Id);
item.SubItems.Add(product.Name);
item.SubItems.Add(product.Price.ToString("F2"));
item.SubItems.Add(product.Stock.ToString());
item.SubItems.Add(product.Date.ToShortDateString());
// 添加自定义标签(存储对象引用)
item.Tag = product;
listViewData.Items.Add(item);
}
}
}
finally
{
// 结束更新,刷新UI
listViewData.EndUpdate();
}
UpdateStatus($"批量添加完成,共{products.Count}条记录");
}
// 数据验证
private bool ValidateProduct(Product product)
{
if (string.IsNullOrWhiteSpace(product.Name))
{
MessageBox.Show("产品名称不能为空", "验证错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
if (product.Price <= 0)
{
MessageBox.Show("价格必须大于0", "验证错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
if (product.Stock < 0)
{
MessageBox.Show("库存不能为负数", "验证错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
return true;
}
}
// 产品数据模型类
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int Stock { get; set; }
public DateTime Date { get; set; }
}
```
## 3. 删除行数据的多种实现方式
### 3.1 删除选中行(基础方法)
```csharp
// 方法1:删除当前选中的行 [ref_5]
private void btnDeleteSelected_Click(object sender, EventArgs e)
{
// 检查是否有选中的行
if (listViewData.SelectedItems.Count == 0)
{
MessageBox.Show("请先选择要删除的行", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// 获取选中的项
ListViewItem selectedItem = listViewData.SelectedItems[0];
string productName = selectedItem.SubItems[1].Text; // 获取产品名称
// 确认删除
DialogResult result = MessageBox.Show(
$"确定要删除产品 '{productName}' 吗?",
"确认删除",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
// 删除选中项 [ref_6]
listViewData.Items.Remove(selectedItem);
UpdateStatus($"已删除产品: {productName}");
}
}
// 方法2:通过索引删除
private void DeleteByIndex(int index)
{
if (index >= 0 && index < listViewData.Items.Count)
{
string itemText = listViewData.Items[index].Text;
listViewData.Items.RemoveAt(index);
UpdateStatus($"已删除索引 {index} 的项: {itemText}");
}
}
// 方法3:删除所有选中的行(支持多选)
private void DeleteAllSelected()
{
if (listViewData.SelectedItems.Count == 0)
return;
// 获取要删除的产品名称列表
List<string> deletedProducts = new List<string>();
foreach (ListViewItem item in listViewData.SelectedItems)
{
deletedProducts.Add(item.SubItems[1].Text);
}
// 确认删除
string message = $"确定要删除以下 {deletedProducts.Count} 个产品吗?\n" +
string.Join("\n", deletedProducts);
if (MessageBox.Show(message, "批量删除确认",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
// 必须从后往前删除,因为删除后索引会变化
for (int i = listViewData.SelectedItems.Count - 1; i >= 0; i--)
{
listViewData.Items.Remove(listViewData.SelectedItems[i]);
}
UpdateStatus($"已批量删除 {deletedProducts.Count} 个产品");
}
}
```
### 3.2 右键菜单删除(增强用户体验)
```csharp
using System.Windows.Forms;
public partial class MainForm : Form
{
private ContextMenuStrip contextMenu;
private void InitializeContextMenu()
{
// 创建右键菜单 [ref_6]
contextMenu = new ContextMenuStrip();
// 添加菜单项
ToolStripMenuItem deleteItem = new ToolStripMenuItem("删除选中行");
deleteItem.Click += DeleteContextMenuItem_Click;
deleteItem.Image = SystemIcons.Error.ToBitmap(); // 添加图标
ToolStripMenuItem editItem = new ToolStripMenuItem("编辑");
editItem.Click += EditContextMenuItem_Click;
ToolStripMenuItem copyItem = new ToolStripMenuItem("复制");
copyItem.Click += CopyContextMenuItem_Click;
// 添加到菜单
contextMenu.Items.AddRange(new ToolStripItem[] { editItem, deleteItem, copyItem });
// 关联到ListView
listViewData.ContextMenuStrip = contextMenu;
}
// 右键菜单删除事件
private void DeleteContextMenuItem_Click(object sender, EventArgs e)
{
DeleteSelectedItem();
}
// 支持键盘Delete键删除
private void listViewData_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Delete)
{
DeleteSelectedItem();
e.Handled = true; // 阻止默认行为
}
}
private void DeleteSelectedItem()
{
if (listViewData.SelectedItems.Count > 0)
{
ListViewItem item = listViewData.SelectedItems[0];
string itemInfo = $"ID: {item.Text}, 名称: {item.SubItems[1].Text}";
if (MessageBox.Show($"确定删除?\n{itemInfo}", "确认删除",
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
listViewData.Items.Remove(item);
// 可选:记录删除操作
LogDeletion(itemInfo);
}
}
}
private void LogDeletion(string itemInfo)
{
// 在实际应用中,这里可以记录到日志文件或数据库
string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - 删除记录: {itemInfo}";
System.Diagnostics.Debug.WriteLine(logMessage);
}
}
```
### 3.3 条件删除与批量操作
```csharp
public partial class MainForm : Form
{
// 根据条件删除行(如删除库存为0的行)
private void DeleteByCondition(string condition, object value)
{
int deletedCount = 0;
// 从后往前遍历,避免索引问题
for (int i = listViewData.Items.Count - 1; i >= 0; i--)
{
ListViewItem item = listViewData.Items[i];
bool shouldDelete = false;
switch (condition)
{
case "stock":
if (int.TryParse(item.SubItems[3].Text, out int stock) && stock == (int)value)
shouldDelete = true;
break;
case "price":
if (decimal.TryParse(item.SubItems[2].Text, out decimal price) && price < (decimal)value)
shouldDelete = true;
break;
case "date":
if (DateTime.TryParse(item.SubItems[4].Text, out DateTime date) &&
date < (DateTime)value)
shouldDelete = true;
break;
}
if (shouldDelete)
{
listViewData.Items.RemoveAt(i);
deletedCount++;
}
}
UpdateStatus($"根据条件 '{condition}' 删除了 {deletedCount} 条记录");
}
// 删除所有行
private void ClearAllData()
{
if (listViewData.Items.Count == 0)
return;
if (MessageBox.Show($"确定要清空所有数据吗?共 {listViewData.Items.Count} 条记录",
"清空确认", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
listViewData.Items.Clear();
UpdateStatus("已清空所有数据");
}
}
}
```
## 4. 完整示例:带数据持久化的ListView管理器
```csharp
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
namespace ListViewDataManager
{
public partial class MainForm : Form
{
private List<Product> products = new List<Product>();
private string dataFile = "products.xml";
public MainForm()
{
InitializeComponent();
InitializeListView();
LoadData();
}
private void InitializeListView()
{
// 设置ListView属性
listViewProducts.View = View.Details;
listViewProducts.FullRowSelect = true;
listViewProducts.GridLines = true;
listViewProducts.MultiSelect = false;
// 添加列
listViewProducts.Columns.Add("ID", 80);
listViewProducts.Columns.Add("产品名称", 150);
listViewProducts.Columns.Add("分类", 100);
listViewProducts.Columns.Add("单价", 80);
listViewProducts.Columns.Add("库存", 70);
listViewProducts.Columns.Add("最后更新", 120);
// 设置右键菜单
InitializeContextMenu();
// 启用键盘事件
listViewProducts.KeyDown += ListViewProducts_KeyDown;
}
// 加载数据
private void LoadData()
{
if (File.Exists(dataFile))
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Product>));
using (StreamReader reader = new StreamReader(dataFile))
{
products = (List<Product>)serializer.Deserialize(reader);
RefreshListView();
}
}
catch (Exception ex)
{
MessageBox.Show($"加载数据失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
// 保存数据
private void SaveData()
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Product>));
using (StreamWriter writer = new StreamWriter(dataFile))
{
serializer.Serialize(writer, products);
}
}
catch (Exception ex)
{
MessageBox.Show($"保存数据失败: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// 刷新ListView显示
private void RefreshListView()
{
listViewProducts.Items.Clear();
listViewProducts.BeginUpdate();
foreach (Product product in products)
{
ListViewItem item = new ListViewItem(product.Id);
item.SubItems.Add(product.Name);
item.SubItems.Add(product.Category);
item.SubItems.Add(product.Price.ToString("F2"));
item.SubItems.Add(product.Stock.ToString());
item.SubItems.Add(product.LastUpdated.ToString("yyyy-MM-dd HH:mm"));
// 库存预警颜色
if (product.Stock < 10)
item.ForeColor = Color.Red;
else if (product.Stock < 50)
item.ForeColor = Color.Orange;
item.Tag = product; // 存储对象引用
listViewProducts.Items.Add(item);