我有一个ListView(WinForms),我想通过单击按钮上下移动项目。要移动的项目是选中的项目。因此,如果项目2,6和9被选中,当我按下按钮向上移动时,它们将变成1,5和8,在这些地方的项目被向下移动一步。
我觉得我把这件事搞得不必要复杂了,你可以在下面看到。每个ListViewItem的第二个SubItem是一个数字,表示它在列表中的位置(从1开始)。
我把下面的代码归咎于睡眠不足和咖啡不足,但是如果你能找到一个更简单的方法来完成这个任务,我会很感激的。
private void sourceMoveUpButton_Click(object sender, EventArgs e)
{
List<Int32> affectedNumbers = new List<Int32>();
bool foundNonChecked = false;
List<KeyValuePair<int, ListViewItem>> newList = new List<KeyValuePair<int, ListViewItem>>();
foreach (ListViewItem item in this.sourceListView.CheckedItems)
{
int newNum = int.Parse(item.SubItems[1].Text) - 1;
if (newNum >= 1)
{
foreach (ListViewItem testItem in this.sourceListView.Items)
{
if (int.Parse(testItem.SubItems[1].Text) == newNum && !testItem.Checked)
{
foundNonChecked = true;
}
}
if (foundNonChecked)
{
item.SubItems[1].Text = newNum.ToString();
affectedNumbers.Add(newNum);
}
}
}
foreach (ListViewItem item in this.sourceListView.Items)
{
int num = int.Parse(item.SubItems[1].Text);
if (affectedNumbers.Contains(num) && !item.Checked)
{
item.SubItems[1].Text = (num + affectedNumbers.Count).ToString();
}
newList.Add(new KeyValuePair<int, ListViewItem>(int.Parse(item.SubItems[1].Text), item));
item.Remove();
}
newList.Sort((firstPair, secondPair) =>
{
return firstPair.Key.CompareTo(secondPair.Key);
}
);
foreach (KeyValuePair<int, ListViewItem> pair in newList)
{
this.sourceListView.Items.Add(pair.Value);
}
}
编辑我已将其缩短为以下内容:
foreach (ListViewItem item in this.sourceListView.CheckedItems)
{
if (item.Index > 0)
{
int newIndex = item.Index - 1;
this.sourceListView.Items.RemoveAt(item.Index);
this.sourceListView.Items.Insert(newIndex, item);
}
}
int index = 1;
foreach (ListViewItem item in this.sourceListView.Items)
{
item.SubItems[1].Text = index.ToString();
index++;
}
但现在,如果我选择两个最上面的项目(或类似的),他们将切换位置时,我点击按钮向上移动。
第二版**
所有的工作都很好向上移动,如下:
if (this.sourceListView.CheckedItems[0].Index != 0)
{
this.sourceListView.BeginUpdate();
foreach (ListViewItem item in this.sourceListView.CheckedItems)
{
if (item.Index > 0)
{
int newIndex = item.Index - 1;
this.sourceListView.Items.RemoveAt(item.Index);
this.sourceListView.Items.Insert(newIndex, item);
}
}
this.updateListIndexText();
this.sourceListView.EndUpdate();
}
但对于向下运动,我似乎无法正确地理解:
if (this.sourceListView.CheckedItems[this.sourceListView.CheckedItems.Count - 1].Index < this.sourceListView.Items.Count - 1)
{
this.sourceListView.BeginUpdate();
foreach (ListViewItem item in this.sourceListView.CheckedItems)
{
if (item.Index < this.sourceListView.Items.Count - 1)
{
int newIndex = item.Index + 1;
this.sourceListView.Items.RemoveAt(item.Index);
this.sourceListView.Items.Insert(newIndex, item);
}
}
this.updateListIndexText();
this.sourceListView.EndUpdate();
}
它适用于向下移动单个项目,但当我选择多个项目时,它不起作用。
7条答案
按热度按时间ff29svar1#
试试这样的方法:
基本上只是删除项目,然后插入它上面的地方,它曾经是。ListView会自动处理在插入后按顺序排列的项目,所以不用担心。
wrap-around
移动)。然而,第二个项目是自由移动的,因此进入列表的顶部。要解决这个问题,你可以做以下两件事情之一:
1.实施一个环绕式的重组(即顶部项目到底部)
1.如果选中了顶部项目,则禁止任何移动(选中listview. Items [0]. Selected)
至于文本的重做,就在原来的循环中做。
采用环绕式实现:
编辑二:
静态帮助器实现,无回绕:
示例:
3lxsmp7m2#
为了完成@Jason Larkes的答案,使其正确地支持“向下移动”,请在他提供的MoveListViewItems函数的foreach之前添加这个:
然后迭代使用:
而不是原来的foreach。
很管用。@EClaesson -我希望这能克服你在评论中提到的问题。
xlpyo6sf3#
这是带换行的,所以如果你向下移动索引0的项目,它将到达最后一个位置,如果你向上移动最后一个项目,它将在列表的第一个位置:
tkclm6bt4#
带wrap around的代码:
ubof19bj5#
你的回答不太管用,朋友。在这里我的代码工作完美...
mm9b1k5b6#
仅用于完整,基于'Jason Larke'静态助手解决方案:
该解决方案不移动相邻的项目,这可以使用堆栈这样做:
2g32fytz7#
在静态帮助器类中使用它。它可以完美地工作在多个移动向上和向下。如果你想往下走,你的清单必须颠倒过来。