Items in ListvView nach Drag&Drop neu anordnen
-
Hallo!
Ich knabbere gerade an einem sehr komischen Problem:
Ich habe eine ListView Komponente lvPhotos, bei der ich nach einer Drag&Drop Aktion die ausgewählten Items an ihre neue (durch die Drag&Drop Aktion angegebene) Position verschieben möchte. Um dies zu erreichen kopiere ich die ausgewählten Items in ein ListViewItems Array und erstelle danach ein neues ListViewItems Array, in dem ich alle Items neu anordne (ich kopiere die Items aus lvPhotos und füge an den gewünschten Positionen die Items aus meinem Selected Items Array ein).Hier ist der Code:
private void lvPhotos_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { // get the new location of the items Point p = lvPhotos.PointToClient(new Point(e.X, e.Y)); int destIndex = lvPhotos.GetItemAt(p.X, p.Y).Index; // create a new ListViewItems array ListViewItem[] selItems = new ListViewItem[lvPhotos.SelectedItems.Count]; int[] selIndices = new int[lvPhotos.SelectedIndices.Count]; // create the listViewItems array that will be used instead of the currently displayed one ListViewItem[] newItems = new ListViewItem[lvPhotos.Items.Count]; for(int i = 0; i < selItems.Length; i++) { if(lvPhotos.SelectedIndices[i] == destIndex) // if any of the selectedIndices is equal to the destIndex abort the operation return; // fill the array with the currently selected items selItems[i] = (ListViewItem) lvPhotos.Items[lvPhotos.SelectedIndices[i]].Clone(); // add the current selectedIndex to the selIndices array selIndices[i] = lvPhotos.SelectedIndices[i]; } // delete the selectedItems for(int i = 0; i < selIndices.Length; i++) lvPhotos.Items.RemoveAt(selIndices[i] - i); // recalculate the position of the items that need to be inserted destIndex = lvPhotos.GetItemAt(p.X, p.Y).Index; // fill the new listViewItems array int j = 0; for(int i = 0; i < newItems.Length; i++) { if(i == selIndices[j]) { // if the current item is one that needs to be moved insert it from the selItems list newItems[i] = selItems[j]; j++; } else // just insert the current item from the lv newItems[i] = (ListViewItem) lvPhotos.Items[i - j].Clone(); } // clear the lv and fill it with the newItems lvPhotos.Clear(); lvPhotos.Items.AddRange(newItems); // refresh lvPhotos lvPhotos.Refresh(); }
Das Problem ist, dass anstatt verschoben zu werden, die SelectedItems immer gelöscht werden.
Danke schon mal im Voraus!
-
Mittlerweile bin ich schon etwas weitergekommen: Ich habe den Code etwas optimiert und meine generelle Taktik geändert. Ich erstelle keine neue List sondern reihe die Alte einfach um. Das Problem dabei ist, dass die ListView Komponente keine Umreihungen in meinem View-Mode (LargeIcons) erlaubt. Also setze ich den View temprär auf List, ordne dann die Items neu an und setze den View wieder zurück. Das blöde an der Sache ist, dass das Zurücksetzten auf LargeIcons nicht funktioniert
und ich verstehe einfach nicht warum.
Hier ist der neue Code:
private void lvPhotos_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { // get the new location of the items Point p = lvPhotos.PointToClient(new Point(e.X, e.Y)); int destIndex = lvPhotos.GetItemAt(p.X, p.Y).Index; // create a new ListViewItems array ListViewItem[] selItems = new ListViewItem[lvPhotos.SelectedItems.Count]; int[] selIndices = new int[lvPhotos.SelectedIndices.Count]; // create the listViewItems array that will be used instead of the currently displayed one ListViewItem[] newItems = new ListViewItem[lvPhotos.Items.Count]; for(int i = 0; i < selItems.Length; i++) { if(lvPhotos.SelectedIndices[i] == destIndex) // if any of the selectedIndices is equal to the destIndex abort the operation return; // fill the array with the currently selected items selItems[i] = (ListViewItem) lvPhotos.Items[lvPhotos.SelectedIndices[i]].Clone(); // add the current selectedIndex to the selIndices array selIndices[i] = lvPhotos.SelectedIndices[i]; } // rearrange the photos in the album and break the operation if it can't be saved if(DoAlbumDragDrop(selIndices, destIndex) == false) return; // switch the lvPhotos view to List, since we can't edit the item arrangement in LargeIcon view lvPhotos.View = View.List; // add the items to lvPhotos for(int i = selItems.Length - 1; i >= 0; i--) lvPhotos.Items.Insert(destIndex, selItems[i]); // remove the old items from lvPhotos foreach(ListViewItem item in lvPhotos.SelectedItems) lvPhotos.Items.Remove(item); // create a temp ImageList ImageList ilTemp = new ImageList(); // fill the temp il with the photos in rearranged order for(int i = 0; i < ilThumbs.Images.Count; i++) { if(i == destIndex) { int j; for(j = selIndices.Length - 1; j >= 0; j--) ilTemp.Images.Add(ilThumbs.Images[j]); j = 0; for(i = i; i < ilThumbs.Images.Count; i++) { if(i == selIndices[j]) j++; else ilTemp.Images.Add(ilThumbs.Images[i + j]); } break; } ilTemp.Images.Add(ilThumbs.Images[i]); } // replace the current il with ilTemp ilThumbs.Images.Clear(); for(int i = 0; i < ilTemp.Images.Count; i++) { ilThumbs.Images.Add(ilTemp.Images[i]); lvPhotos.Items[i].ImageIndex = i; } // reset the lvPhotos view lvPhotos.View = View.LargeIcon; }