问题描述
我有一个ListView(的WinForms),其中我想用一个按钮,点击上下移动项目。要被移动的物品是被检查谁的那些。因此,如果9项2,6和选择,他们将成为1,5和8时,我preSS运动向上按钮和制在那些地方的项目向下移动的步骤。
我觉得我做了这个过于复杂,因为你可以看到下面。每一个ListViewItem的第二个分项目是一个数字至极重presents它的位置在列表中(公历1)。
我责怪睡眠不足和咖啡以下code,但是如果你能想出一个简单的方法来完成这个任务,我会心存感激。
私人无效sourceMoveUpButton_Click(对象发件人,EventArgs的)
{
名单<的Int32> affectedNumbers =新的名单,其中,的Int32>();
布尔foundNonChecked = FALSE;
名单< KeyValuePair< INT,ListViewItem的>> newList =新的名单,其中,KeyValuePair< INT,ListViewItem的>>();
的foreach(在this.sourceListView.CheckedItems ListViewItem的项目)
{
INT newNum = int.Parse(item.SubItems [1]。文) - 1;
如果(newNum> = 1)
{
的foreach(ListViewItem的testItem在this.sourceListView.Items)
{
如果(int.Parse(testItem.SubItems [1]。文)== newNum&安培;&安培;!testItem.Checked)
{
foundNonChecked = TRUE;
}
}
如果(foundNonChecked)
{
item.SubItems [1]。文= newNum.ToString();
affectedNumbers.Add(newNum);
}
}
}
的foreach(在this.sourceListView.Items ListViewItem的项目)
{
INT NUM = int.Parse(item.SubItems [1]。文);
如果(affectedNumbers.Contains(NUM)及&安培;!item.Checked)
{
item.SubItems [1]。文=(NUM + affectedNumbers.Count)的ToString();
}
newList.Add(新KeyValuePair< INT,ListViewItem的>(int.Parse(item.SubItems [1]。文),项目));
item.Remove();
}
newList.Sort((firstPair,secondPair)=>
{
返回firstPair.Key.CompareTo(secondPair.Key);
}
);
的foreach(KeyValuePair< INT,ListViewItem的>对在newList)
{
this.sourceListView.Items.Add(pair.Value);
}
}
修改我有短路它归结为以下几点:
的foreach(在this.sourceListView.CheckedItems ListViewItem的项目)
{
如果(item.Index大于0)
{
INT newIndex = item.Index - 1;
this.sourceListView.Items.RemoveAt(item.Index);
this.sourceListView.Items.Insert(newIndex,项目);
}
}
INT索引= 1;
的foreach(在this.sourceListView.Items ListViewItem的项目)
{
item.SubItems [1]。文= index.ToString();
指数++;
}
但现在,如果我选择两个最上面的项目(或类似),他们将切换的地方,当我点击该按钮上移。
第二次修改一切正常的向上运动与以下内容:
如果(this.sourceListView.CheckedItems [0] .Index!= 0)
{
this.sourceListView.BeginUpdate();
的foreach(在this.sourceListView.CheckedItems ListViewItem的项目)
{
如果(item.Index大于0)
{
INT newIndex = item.Index - 1;
this.sourceListView.Items.RemoveAt(item.Index);
this.sourceListView.Items.Insert(newIndex,项目);
}
}
this.updateListIndexText();
this.sourceListView.EndUpdate();
}
但对于向下运动我似乎无法得到它的权利:
如果(this.sourceListView.CheckedItems [this.sourceListView.CheckedItems.Count - 1] .Index< this.sourceListView.Items.Count - 1)
{
this.sourceListView.BeginUpdate();
的foreach(在this.sourceListView.CheckedItems ListViewItem的项目)
{
如果(item.Index< this.sourceListView.Items.Count - 1)
{
INT newIndex = item.Index + 1;
this.sourceListView.Items.RemoveAt(item.Index);
this.sourceListView.Items.Insert(newIndex,项目);
}
}
this.updateListIndexText();
this.sourceListView.EndUpdate();
}
它适用于移动的单品了,但是当我选择一个以上的,事实并非如此。
尝试是这样的:
的foreach(ListViewItem的LVI在sourceListView.SelectedItems)
{
如果(lvi.Index大于0)
{
INT指数= lvi.Index - 1;
sourceListView.Items.RemoveAt(lvi.Index);
sourceListView.Items.Insert(索引,LVI);
}
}
基本上只是删除了项目,然后上面的地方曾经是将其插入。 ListView控件自动处理的洗牌下了订单的物品插入后,所以不用担心。
编辑:究其原因这两个最上面的物品交换是在顶端的项目将不会移动(即我还没有实施环绕式
的举动。第二项,然而,是免费的移动,从而进入到列表的顶部。
要解决这个问题,你可以做1 2件事情:
对于重新做文字,只是做在原来的循环。
执行与概括的:
的foreach(ListViewItem的LVI在sourceListView.SelectedItems)
{
INT指数= lvi.Index> 0? lvi.Index - 1:sourceListView.Items.Count - 1;
sourceListView.Items.RemoveAt(lvi.Index);
sourceListView.Items.Insert(索引,LVI);
如果(指数= sourceListView.Items.Count - 1!)//不是一个概括:
{
//刚过互换指数。
sourceListView.Items [索引+ 1] .SubItems [1]。文=(索引+ 1)的ToString();
lvi.SubItems [1]。文= index.ToString();
}
否则//项目缠,必须手动更新所有项目。
{
的foreach(ListViewItem的lvi2在sourceListView.Items)
lvi2.SubItems [1]。文= lvi2.Index.ToString();
}
}
编辑2:
静态辅助实施,无环绕:
私人枚举MoveDirection {向上= -1,关闭= 1};
私有静态无效MoveListViewItems(ListView的发件人,MoveDirection方向)
{
INT DIR =(int)的方向;
INT OPP = DIR * -1;
布尔有效= sender.SelectedItems.Count> 0安培;&安培;
((方向== MoveDirection.Down&安培;及(sender.SelectedItems [sender.SelectedItems.Count - 1] .Index&其中; sender.Items.Count - 1))
|| (方向== MoveDirection.Up&安培;及(sender.SelectedItems [0] .Index大于0)));
如果(有效)
{
的foreach(在sender.SelectedItems ListViewItem的项目)
{
INT指数= item.Index +方向;
sender.Items.RemoveAt(item.Index);
sender.Items.Insert(索引项);
sender.Items [指数+ OPP] .SubItems [1]。文=(指数+ OPP)的ToString();
item.SubItems [1]。文=(索引)的ToString();
}
}
}
例如:
MoveListViewItems(sourceListView,MoveDirection.Up);
MoveListviewItems(sourceListview,MoveDirection.Down);
I have a ListView (WinForms) in which i want to move items up and down with the click of a button. The items to be moved are the ones who are checked. So if item 2, 6 and 9 are selected, they will become 1, 5 and 8 when i press the button for movement upwards and the items that were on those places are moved down a step.
I feel that i have made this unnecessarily complicated, as you can see below. The second SubItem of each ListViewItem is a number wich represents its place in the list (starts on 1).
I blame lack of sleep and coffe for the following code, but if you could figure out a simpler way to complete this task i would be thankful.
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);
}
}
EDITI have shorted it down to the following:
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++;
}
But now, if i select the two topmost items (or similar) they will switch place when i click the button for upwards movement.
SECOND EDITEverything works fine for upwards movement with the following:
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();
}
But for downward movement i can't seem to get it right:
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();
}
It works for moving single items down, but when i select more than one, it doesn't.
Try something like this:
foreach (ListViewItem lvi in sourceListView.SelectedItems)
{
if (lvi.Index > 0)
{
int index = lvi.Index - 1;
sourceListView.Items.RemoveAt(lvi.Index);
sourceListView.Items.Insert(index, lvi);
}
}
Basically just removes the item then inserts it above of where it used to be. The ListView automatically handles reshuffling the items down the order after an insert so no worries.
Edit:The reason the two topmost items swap is that the top item will never move (i.e I haven't implemented a wrap-around
move. The 2nd item, however, is free to move and thus goes to the top of the list.
To resolve this, you can do 1 of 2 things:
As for the re-doing of the text, just do it in the original loop.
Implementation with wraparound:
foreach (ListViewItem lvi in sourceListView.SelectedItems)
{
int index = lvi.Index > 0 ? lvi.Index - 1 : sourceListView.Items.Count - 1;
sourceListView.Items.RemoveAt(lvi.Index);
sourceListView.Items.Insert(index, lvi);
if (index != sourceListView.Items.Count - 1) //not a wraparound:
{
//just swap the indices over.
sourceListView.Items[index + 1].SubItems[1].Text = (index + 1).ToString();
lvi.SubItems[1].Text = index.ToString();
}
else //item wrapped around, have to manually update all items.
{
foreach (ListViewItem lvi2 in sourceListView.Items)
lvi2.SubItems[1].Text = lvi2.Index.ToString();
}
}
Edit 2:
Static helper implementation, no wrap-around:
private enum MoveDirection { Up = -1, Down = 1 };
private static void MoveListViewItems(ListView sender, MoveDirection direction)
{
int dir = (int)direction;
int opp = dir * -1;
bool valid = sender.SelectedItems.Count > 0 &&
((direction == MoveDirection.Down && (sender.SelectedItems[sender.SelectedItems.Count - 1].Index < sender.Items.Count - 1))
|| (direction == MoveDirection.Up && (sender.SelectedItems[0].Index > 0)));
if (valid)
{
foreach (ListViewItem item in sender.SelectedItems)
{
int index = item.Index + dir;
sender.Items.RemoveAt(item.Index);
sender.Items.Insert(index, item);
sender.Items[index + opp].SubItems[1].Text = (index + opp).ToString();
item.SubItems[1].Text = (index).ToString();
}
}
}
Example:
MoveListViewItems(sourceListView, MoveDirection.Up);
MoveListviewItems(sourceListview, MoveDirection.Down);
这篇关于移动ListViewItems向上和向下的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!