Moving an item up and down in a WPF list box
I make some 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));
}
There is no need to know the ListBox for this.
Since you have populated the listbox by binding to a ObservableCollection using ItemsSource, you cant modify the Items property of the listbox.
ItemsSource can be set only when the Items collection is empty, and Items can be modified only when ItemsSource is null.
Otherwise you will get the error "Operation is not valid while ItemsSource is in use..."
What you have to do, is modify the underlying collection, and because it's an ObservableCollection, the ListBox will reflect the changes.
The following code shows how you can move an item up and down by swapping the item in the collection.
The corresponding XAML just contains a listbox called lbItems and 2 buttons which hook up the eventhandlers.
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;
}
}
}
This is the easiest way to do this and it fires all the right events so you don't have to worry about XAML. ObservableCollection has a nice method called
MoveItem(previousIndex, newIndex)
Given that you have a 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 preceding item.
Simple as that!