在C# WinForms开发中,获取ListView选中行的索引是进行后续操作(如删除、编辑、查看详情)的基础。ListView提供了多种方式来获取选中项的信息,包括索引、值和完整的行数据。下面将详细介绍各种获取方法及其应用场景。
## 1. 获取选中行索引的基本方法
### 1.1 使用SelectedIndices属性(推荐方法)
`SelectedIndices`属性返回一个包含所有选中项索引的集合,这是最常用且最安全的方法:
```csharp
using System;
using System.Windows.Forms;
public partial class MainForm : Form
{
private ListView listView1;
// 方法1:获取第一个选中项的索引 [ref_2]
private int GetFirstSelectedIndex()
{
// 检查是否有选中的项
if (listView1.SelectedIndices.Count == 0)
{
// 没有选中项,返回-1表示无选中
return -1;
}
// 获取第一个选中项的索引
int selectedIndex = listView1.SelectedIndices[0];
return selectedIndex;
}
// 方法2:获取所有选中项的索引
private List<int> GetAllSelectedIndices()
{
List<int> indices = new List<int>();
// 遍历所有选中项的索引
foreach (int index in listView1.SelectedIndices)
{
indices.Add(index);
}
return indices;
}
// 方法3:通过按钮点击获取并显示索引
private void btnGetIndex_Click(object sender, EventArgs e)
{
int index = GetFirstSelectedIndex();
if (index >= 0)
{
MessageBox.Show($"选中的行索引是: {index}",
"索引信息",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
MessageBox.Show("请先选择一行数据",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
}
}
}
```
### 1.2 使用SelectedItems属性(通过项获取索引)
`SelectedItems`属性返回选中项的集合,可以通过项来获取索引:
```csharp
// 方法4:通过SelectedItems获取索引
private int GetSelectedIndexViaItems()
{
if (listView1.SelectedItems.Count == 0)
return -1;
// 获取第一个选中项
ListViewItem selectedItem = listView1.SelectedItems[0];
// 通过项的Index属性获取索引
int index = selectedItem.Index;
return index;
}
// 方法5:获取多选情况下的所有索引
private void GetMultiSelectedIndices()
{
if (listView1.SelectedItems.Count == 0)
{
MessageBox.Show("没有选中的行");
return;
}
string indicesText = "选中的行索引:\n";
foreach (ListViewItem item in listView1.SelectedItems)
{
indicesText += $"第 {item.Index} 行: {item.Text}\n";
}
MessageBox.Show(indicesText, "多选索引信息");
}
```
## 2. 事件驱动方式获取索引
### 2.1 ItemSelectionChanged事件
这是最常用的事件,当选中状态改变时触发:
```csharp
using System.Windows.Forms;
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
InitializeListView();
SetupEvents();
}
private void SetupEvents()
{
// 绑定选中改变事件 [ref_2]
listViewData.ItemSelectionChanged += ListViewData_ItemSelectionChanged;
// 绑定点击事件
listViewData.Click += ListViewData_Click;
// 绑定双击事件
listViewData.DoubleClick += ListViewData_DoubleClick;
}
// ItemSelectionChanged事件处理 [ref_2]
private void ListViewData_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
// e.IsSelected表示该项是否被选中
if (e.IsSelected)
{
int selectedIndex = e.ItemIndex;
string itemText = e.Item.Text;
// 更新状态栏显示选中信息
UpdateStatus($"选中第 {selectedIndex} 行: {itemText}");
// 可以在这里执行其他操作,如启用/禁用按钮
btnDelete.Enabled = true;
btnEdit.Enabled = true;
}
else
{
// 取消选中时的处理
if (listViewData.SelectedItems.Count == 0)
{
btnDelete.Enabled = false;
btnEdit.Enabled = false;
}
}
}
// Click事件处理
private void ListViewData_Click(object sender, EventArgs e)
{
// 获取当前选中的索引
if (listViewData.SelectedIndices.Count > 0)
{
int index = listViewData.SelectedIndices[0];
// 获取选中行的所有数据
ListViewItem selectedItem = listViewData.Items[index];
string rowData = $"行 {index} 的数据:\n";
for (int i = 0; i < selectedItem.SubItems.Count; i++)
{
rowData += $"列{i}: {selectedItem.SubItems[i].Text}\n";
}
// 在标签中显示
lblSelectionInfo.Text = rowData;
}
}
// DoubleClick事件处理
private void ListViewData_DoubleClick(object sender, EventArgs e)
{
if (listViewData.SelectedIndices.Count > 0)
{
int index = listViewData.SelectedIndices[0];
OpenDetailView(index);
}
}
private void OpenDetailView(int index)
{
// 打开详细视图窗口,传入索引
DetailForm detailForm = new DetailForm(index, listViewData.Items[index]);
detailForm.ShowDialog();
}
private void UpdateStatus(string message)
{
toolStripStatusLabel1.Text = message;
}
}
```
### 2.2 MouseClick事件(支持右键菜单)
```csharp
// MouseClick事件处理,特别适用于右键菜单 [ref_6]
private void listViewData_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right) // 右键点击
{
// 获取点击位置的项
ListViewItem clickedItem = listViewData.GetItemAt(e.X, e.Y);
if (clickedItem != null)
{
// 选中该项
clickedItem.Selected = true;
// 获取索引
int index = clickedItem.Index;
// 显示右键菜单
ShowContextMenu(index, e.Location);
}
}
}
private void ShowContextMenu(int index, Point location)
{
ContextMenuStrip contextMenu = new ContextMenuStrip();
// 添加菜单项,传入索引作为参数
ToolStripMenuItem viewItem = new ToolStripMenuItem($"查看第 {index} 行详情");
viewItem.Tag = index; // 将索引存储在Tag中
viewItem.Click += (s, args) =>
{
int itemIndex = (int)((ToolStripMenuItem)s).Tag;
ViewItemDetails(itemIndex);
};
ToolStripMenuItem deleteItem = new ToolStripMenuItem($"删除第 {index} 行");
deleteItem.Tag = index;
deleteItem.Click += (s, args) =>
{
int itemIndex = (int)((ToolStripMenuItem)s).Tag;
DeleteItem(itemIndex);
};
contextMenu.Items.Add(viewItem);
contextMenu.Items.Add(deleteItem);
contextMenu.Show(listViewData, location);
}
```
## 3. 获取选中行数据(结合索引)
获取索引后,通常需要进一步获取该行的具体数据:
```csharp
public partial class MainForm : Form
{
// 方法:根据索引获取整行数据
private string[] GetRowDataByIndex(int index)
{
if (index < 0 || index >= listViewData.Items.Count)
{
throw new ArgumentOutOfRangeException("索引超出范围");
}
ListViewItem item = listViewData.Items[index];
string[] rowData = new string[item.SubItems.Count];
for (int i = 0; i < item.SubItems.Count; i++)
{
rowData[i] = item.SubItems[i].Text;
}
return rowData;
}
// 方法:获取选中行的特定列值
private string GetSelectedColumnValue(int columnIndex)
{
if (listViewData.SelectedIndices.Count == 0)
return string.Empty;
int selectedIndex = listViewData.SelectedIndices[0];
ListViewItem selectedItem = listViewData.Items[selectedIndex];
if (columnIndex < 0 || columnIndex >= selectedItem.SubItems.Count)
return string.Empty;
return selectedItem.SubItems[columnIndex].Text;
}
// 方法:获取选中行的对象(如果Tag中存储了对象)
private object GetSelectedItemObject()
{
if (listViewData.SelectedIndices.Count == 0)
return null;
int selectedIndex = listViewData.SelectedIndices[0];
ListViewItem selectedItem = listViewData.Items[selectedIndex];
return selectedItem.Tag; // 返回存储在Tag中的对象
}
// 示例:显示选中行的详细信息
private void ShowSelectedItemDetails()
{
if (listViewData.SelectedIndices.Count == 0)
{
MessageBox.Show("请先选择一行");
return;
}
int index = listViewData.SelectedIndices[0];
ListViewItem item = listViewData.Items[index];
StringBuilder details = new StringBuilder();
details.AppendLine($"行索引: {index}");
details.AppendLine($"主项文本: {item.Text}");
details.AppendLine("所有列的值:");
for (int i = 0; i < item.SubItems.Count; i++)
{
details.AppendLine($" 列{i}: {item.SubItems[i].Text}");
}
// 如果有存储对象
if (item.Tag != null)
{
details.AppendLine($"\n关联对象: {item.Tag.GetType().Name}");
}
MessageBox.Show(details.ToString(), "行详细信息");
}
}
```
## 4. 完整示例:带索引管理的ListView应用
下面是一个完整的示例,演示如何在实际应用中使用索引管理:
```csharp
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace ListViewIndexDemo
{
public partial class MainForm : Form
{
private ListView listViewProducts;
private TextBox txtCurrentIndex;
private Label lblRowInfo;
public MainForm()
{
InitializeComponent();
InitializeListView();
SetupUI();
LoadSampleData();
}
private void InitializeListView()
{
listViewProducts = new ListView
{
Dock = DockStyle.Fill,
View = View.Details,
FullRowSelect = true,
GridLines = true,
MultiSelect = false,
HideSelection = false
};
// 添加列
listViewProducts.Columns.Add("ID", 80);
listViewProducts.Columns.Add("产品名称", 150);
listViewProducts.Columns.Add("分类", 100);
listViewProducts.Columns.Add("价格", 80);
listViewProducts.Columns.Add("库存", 70);
// 绑定事件
listViewProducts.ItemSelectionChanged += ListViewProducts_ItemSelectionChanged;
listViewProducts.KeyDown += ListViewProducts_KeyDown;
this.Controls.Add(listViewProducts);
}
private void SetupUI()
{
// 创建工具栏
ToolStrip toolStrip = new ToolStrip();
ToolStripButton btnGetIndex = new ToolStripButton("获取索引");
btnGetIndex.Click += BtnGetIndex_Click;
ToolStripButton btnGetData = new ToolStripButton("获取数据");
btnGetData.Click += BtnGetData_Click;
ToolStripButton btnDelete = new ToolStripButton("删除行");
btnDelete.Click += BtnDelete_Click;
ToolStripButton btnMoveUp = new ToolStripButton("上移");
btnMoveUp.Click += BtnMoveUp_Click;
ToolStripButton btnMoveDown = new ToolStripButton("下移");
btnMoveDown.Click += BtnMoveDown_Click;
toolStrip.Items.AddRange(new ToolStripItem[]
{
btnGetIndex, btnGetData, btnDelete, btnMoveUp, btnMoveDown
});
// 状态显示
txtCurrentIndex = new TextBox
{
Dock = DockStyle.Bottom,
ReadOnly = true,
BackColor = Color.LightYellow
};
lblRowInfo = new Label
{
Dock = DockStyle.Bottom,
Height = 60,
BorderStyle = BorderStyle.FixedSingle
};
this.Controls.Add(toolStrip);
this.Controls.Add(lblRowInfo);
this.Controls.Add(txtCurrentIndex);
}
private void LoadSampleData()
{
// 添加示例数据
string[,] products = {
{"P001", "笔记本电脑", "电子产品", "5999.00", "45"},
{"P002", "无线鼠标", "电脑配件", "89.50", "120"},
{"P003", "机械键盘", "电脑配件", "399.00", "78"},
{"P004", "显示器", "电子产品", "1299.00", "32"},
{"P005", "办公椅", "家具", "499.00", "15"}
};
for (int i = 0; i < products.GetLength(0); i++)
{
ListViewItem item = new ListViewItem(products[i, 0]);
for (int j = 1; j < products.GetLength(1); j++)
{
item.SubItems.Add(products[i, j]);
}
// 根据库存设置颜色
if (int.TryParse(products[i, 4], out int stock))
{
if (stock < 20)
item.ForeColor = Color.Red;
else if (stock < 50)
item.ForeColor = Color.Orange;
}
listViewProducts.Items.Add(item);
}
}
// 事件处理:选中改变
private void ListViewProducts_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (e.IsSelected)
{
UpdateIndexDisplay(e.ItemIndex);
}
}
// 更新索引显示
private void UpdateIndexDisplay(int index)
{
txtCurrentIndex.Text = $"当前选中索引: {index}";
if (index >= 0)
{
ListViewItem item = listViewProducts.Items[index];
lblRowInfo.Text = $"行 {index}: {item.SubItems[1].Text} | " +
$"价格: {item.SubItems[3].Text} | " +
$"库存: {item.SubItems[4].Text}";
}
}
// 按钮事件:获取索引
private void BtnGetIndex_Click(object sender, EventArgs e)
{
int index = GetSelectedIndex();
if (index >= 0)
{
MessageBox.Show($"选中行的索引是: {index}\n" +
$"总行数: {listViewProducts.Items.Count}\n" +
$"下一行索引: {index + 1}",
"索引信息");
}
}
// 按钮事件:获取数据
private void BtnGetData_Click(object sender, EventArgs e)
{
int index = GetSelectedIndex();
if (index >= 0)
{
string[] rowData = GetRowData(index);
StringBuilder sb = new StringBuilder();
sb.AppendLine($"第 {index} 行数据:");
for (int i = 0; i < rowData.Length; i++)
{
sb.AppendLine($" 列{i}: {rowData[i]}");
}
MessageBox.Show(sb.ToString(), "行数据详情");
}
}
// 按钮事件:删除行
private void BtnDelete_Click(object sender, EventArgs e)
{
int index = GetSelectedIndex();
if (index >= 0)
{
string itemName = listViewProducts.Items[index].SubItems[1].Text;
if (MessageBox.Show($"确定删除 '{itemName}' 吗?",
"确认删除",
MessageBoxButtons.YesNo) == DialogResult.Yes)
{
listViewProducts.Items.RemoveAt(index);
MessageBox.Show("删除成功");
// 如果有其他行,选中下一行
if (listViewProducts.Items.Count > 0)
{
int newIndex = Math.Min(index, listViewProducts.Items.Count - 1);
listViewProducts.Items[newIndex].Selected = true;
}
}
}
}
// 按钮事件:上移行
private void BtnMoveUp_Click(object sender, EventArgs e)
{
int index = GetSelectedIndex();
if (index > 0) // 不是第一行才能上移
{
MoveItem(index, index - 1);
}
}
// 按钮事件:下移行
private void BtnMoveDown_Click(object sender, EventArgs e)
{
int index = GetSelectedIndex();
if (index >= 0 && index < listViewProducts.Items.Count - 1)
{
MoveItem(index, index + 1);
}
}
// 移动行的方法
private void MoveItem(int fromIndex, int toIndex)
{
ListViewItem item = listViewProducts.Items[fromIndex];
listViewProducts.Items.RemoveAt(fromIndex);
listViewProducts.Items.Insert(toIndex, item);
item.Selected = true;
}
// 键盘事件处理
private void ListViewProducts_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Delete:
BtnDelete_Click(sender, e);
break;
case Keys.Up:
if (e.Control)
BtnMoveUp_Click(sender, e);
break;
case Keys.Down:
if (e.Control)
BtnMoveDown_Click(sender, e);
break;
case Keys.F5:
// 刷新显示
UpdateIndex