Move an item up and down in a WPF list box

I have a list with a bunch of values ​​in it. I also have an UP button and a DOWN button. Using these buttons, I would like to move the selected item in the list box up / down. I have problems with this.

Here is my code:

private void btnDataUp_Click(object sender, RoutedEventArgs e) { int selectedIndex = listBoxDatasetValues.SelectedIndex; //get the selected item in the data list if (selectedIndex != -1 && selectedIndex != 0) //if the selected item is selected and not at the top of the list { //swap items here listBoxDatasetValues.SelectedIndex = selectedIndex - 1; //keep the item selected } } 

I do not know how to change the values! Any help would be greatly appreciated!

+7
source share
7 answers

Since you populated the list by binding the ObservableCollection using ItemsSource, you cannot change the Items property in the list.

ItemsSource can only be set when the Items collection is empty, and items can only be changed if the ItemSource is NULL.

Otherwise, you will receive the error message "Operation is not valid when using ItemsSource ..."

What you need to do is change the base collection, and since this is an ObservableCollection, the ListBox will reflect the changes.

The following code shows how you can move an item up and down by replacing an item in a collection.

The corresponding XAML simply contains a list called lbItems, and 2 buttons that connect event handlers.

 public partial class MainWindow : Window { private ObservableCollection<string> ListItems = new ObservableCollection<string> { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6" }; public MainWindow() { InitializeComponent(); lbItems.ItemsSource = this.ListItems; } private void up_click(object sender, RoutedEventArgs e) { var selectedIndex = this.lbItems.SelectedIndex; if (selectedIndex > 0) { var itemToMoveUp = this.ListItems[selectedIndex]; this.ListItems.RemoveAt(selectedIndex); this.ListItems.Insert(selectedIndex - 1, itemToMoveUp); this.lbItems.SelectedIndex = selectedIndex - 1; } } private void down_click(object sender, RoutedEventArgs e) { var selectedIndex = this.lbItems.SelectedIndex; if (selectedIndex + 1 < this.ListItems.Count) { var itemToMoveDown = this.ListItems[selectedIndex]; this.ListItems.RemoveAt(selectedIndex); this.ListItems.Insert(selectedIndex + 1, itemToMoveDown); this.lbItems.SelectedIndex = selectedIndex + 1; } } } 
+20
source

I make several extension methods for this:

  public static void MoveItemUp<T>(this ObservableCollection<T> baseCollection, int selectedIndex) { //# Check if move is possible if (selectedIndex <= 0) return; //# Move-Item baseCollection.Move(selectedIndex - 1, selectedIndex); } public static void MoveItemDown<T>(this ObservableCollection<T> baseCollection, int selectedIndex) { //# Check if move is possible if (selectedIndex < 0 || selectedIndex + 1 >= baseCollection.Count) return; //# Move-Item baseCollection.Move(selectedIndex + 1, selectedIndex); } public static void MoveItemDown<T>(this ObservableCollection<T> baseCollection, T selectedItem) { //# MoveDown based on Item baseCollection.MoveItemDown(baseCollection.IndexOf(selectedItem)); } public static void MoveItemUp<T>(this ObservableCollection<T> baseCollection, T selectedItem) { //# MoveUp based on Item baseCollection.MoveItemUp(baseCollection.IndexOf(selectedItem)); } 

You do not need to know ListBox for this.

+5
source

This is the easiest way to do this, and it fires all the right events, so you don't need to worry about XAML. ObservableCollection has a nice method called

 MoveItem(previousIndex, newIndex) 

Given that you have an ObservableCollection named DataItemList

 public void MoveUp() { var currentIndex = DataItemList.SelectedIndex; //Index of the selected item if (currentIndex > 0) { int upIndex = currentIndex - 1; //move the items DataItemList.MoveItem(upIndex,currentIndex); } } 

For Down, you get the index of the previous item.

Just like that!

+4
source

I would add a comment, but I can not, as I have only 3 reputations: /

Peter Hansen's solution is great, but if there is no item selected, down_click throws an ArgumentOutOfRange exception. This is because if the item is not selected, the index is -1.

I would edit down_click as follows:

 private void down_click(object sender, RoutedEventArgs e) { if (this.lbItems.SelectedIndex != -1) //Added condition { var selectedIndex = this.lbItems.SelectedIndex; if (selectedIndex + 1 < this.ListItems.Count) { var itemToMoveDown = this.ListItems[selectedIndex]; this.ListItems.RemoveAt(selectedIndex); this.ListItems.Insert(selectedIndex + 1, itemToMoveDown); this.lbItems.SelectedIndex = selectedIndex + 1; } } } 
+3
source

try the following:

 if (listBoxDatasetValues.SelectedItems.Count > 0) { object selected = listBoxDatasetValues.SelectedItem; int indx = listBoxDatasetValues.Items.IndexOf(selected); int totl = listBoxDatasetValues.Items.Count; if (indx == 0) { listBoxDatasetValues.Items.Remove(selected); listBoxDatasetValues.Items.Insert(totl - 1, selected); listBoxDatasetValues.SetSelected(totl - 1, true); } else{ listBoxDatasetValues.Items.Remove(selected); listBoxDatasetValues.Items.Insert(indx - 1, selected); listBoxDatasetValues.SetSelected(indx - 1, true); } } 
+1
source
  if(listBoxDatasetValues.ListIndex > 0) { // add a duplicate item up in the listbox listBoxDatasetValues.AddItem(listBoxDatasetValues.Text, listBoxDatasetValues.ListIndex - 1); // make it the current item listBoxDatasetValues.ListIndex = (listBoxDatasetValues.ListIndex - 2); // delete the old occurrence of this item listBoxDatasetValues.RemoveItem(listBoxDatasetValues.ListIndex + 2); } 
+1
source

You can try something like this:

To move up:

 if (listboxName.SelectedIndex == -1 || listboxName.SelectedIndex == 0) return; Object select, previous, temp; select = listboxName.Items[listboxName.SelectedIndex]; previous = listboxName.Items[listboxName.SelectedIndex-1]; temp = select; select = previous; previous = temp; listboxName.Items[listboxName.SelectedIndex] = select; listboxName.Items[listboxName.SelectedIndex-1] = previous; listboxName.SelectedIndex--; 

To move down:

 if (listboxName.SelectedIndex == -1 || listboxName.SelectedIndex == listboxName.Items.Count-1) return; Object select, next, temp; select = listboxName.Items[listboxName.SelectedIndex]; next = listboxName.Items[listboxName.SelectedIndex+1]; temp = select; select = next; next = temp; listboxName.Items[listboxName.SelectedIndex] = select; listboxName.Items[listboxName.SelectedIndex+1] = next; listboxName.SelectedIndex++; 
0
source

All Articles