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;
    		}
    

Anmelden zum Antworten