在C#的WinForms开发中,ListView是展示列表数据的常用控件。为了让用户更直观地调整条目顺序,我们可以同时提供鼠标拖拽排序和按钮上下移动两种交互方式。下面介绍具体的实现思路与代码。

一、启用ListView的拖拽功能
首先需要将ListView的AllowDrop属性设为true,并绑定相关拖放事件。以下代码在窗体加载时完成基础设置:
using System;
using System.Windows.Forms;
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// 假设界面上已拖放一个名为listView1的ListView
listView1.AllowDrop = true;
listView1.ItemDrag += ListView1_ItemDrag;
listView1.DragEnter += ListView1_DragEnter;
listView1.DragDrop += ListView1_DragDrop;
}
private void ListView1_ItemDrag(object sender, ItemDragEventArgs e)
{
// 开始拖拽,传入被拖动的ListViewItem
listView1.DoDragDrop(e.Item, DragDropEffects.Move);
}
private void ListView1_DragEnter(object sender, DragEventArgs e)
{
// 只允许移动操作
if (e.Data.GetDataPresent(typeof(ListViewItem)))
{
e.Effect = DragDropEffects.Move;
}
else
{
e.Effect = DragDropEffects.None;
}
}
}
二、处理拖放完成后的排序逻辑
在DragDrop事件中,我们计算鼠标位置对应的目标项索引,并将被拖动的项插入到正确位置:
private void ListView1_DragDrop(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(ListViewItem)))
{
return;
}
ListViewItem draggedItem = (ListViewItem)e.Data.GetData(typeof(ListViewItem));
Point clientPoint = listView1.PointToClient(new Point(e.X, e.Y));
ListViewItem targetItem = listView1.GetItemAt(clientPoint.X, clientPoint.Y);
if (draggedItem == null || draggedItem == targetItem)
{
return;
}
int targetIndex = targetItem != null ? targetItem.Index : listView1.Items.Count - 1;
listView1.Items.Remove(draggedItem);
listView1.Items.Insert(targetIndex, draggedItem);
}
三、通过按钮实现上下移动
除了拖拽,还可以提供上移和下移按钮,方便精确调整。核心是根据选中项的索引进行交换或移除插入:
private void btnUp_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0)
{
return;
}
ListViewItem item = listView1.SelectedItems[0];
int index = item.Index;
if (index > 0)
{
listView1.Items.RemoveAt(index);
listView1.Items.Insert(index - 1, item);
item.Selected = true;
}
}
private void btnDown_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count == 0)
{
return;
}
ListViewItem item = listView1.SelectedItems[0];
int index = item.Index;
if (index < listView1.Items.Count - 1)
{
listView1.Items.RemoveAt(index);
listView1.Items.Insert(index + 1, item);
item.Selected = true;
}
}
四、注意事项
- 如果ListView绑定了数据源,拖拽后需要同步更新底层集合顺序。
- 使用
GetItemAt()方法时,若落点在空白区域可默认放到末尾。 - 拖拽过程中可配合
DragOver事件高亮目标位置,提升交互体验。
以上方式适用于WinForms场景,若为WPF可使用ListView配合ObservableCollection与拖放行为实现类似效果。
C#ListView拖拽排序ItemDragDoDragDrop修改时间:2026-07-25 02:27:19