tags:

views:

786

answers:

3

Is it possible to sort items in WPF ListBox in reverse from their original order? I mean you can use SortDescriptions to sort by some property, but what if I just need to show the items in the reverse order with no real field to sort against?

Note: I would prefer not to sort the original collection or clone it, etc. I know how to do that but I'm looking for a way to make ListBox do this for presentation only.

Thanks

A: 

A cheap answer would be to add a new integer field to the data object and increment this for each item. Then you can reverse sort on this field. I understand that this might not be a workable solution.

If you use a collection view to sort, I believe you always have to sort based on some property or condition. Sorts are going to be based on a comparison object that implements IComparer. This interface compares two objects and determines which is larger. You can't reverse the sort on this unless you have some way to determine how to order two items by comparing them.

Josh G
Yes, adding an artificial property which would return something like IndexOf from the original collection was my first idea too. But it looked a bit ugly and, as you said, cheap. But seems that this is what I'll do.
Alan Mendelevich
A: 

This is a bit ugly but it will reverse the order of the ListBoxItems in listbox1. You can't do the obvious thing: use a single temp variable and swap two elements per loop iteration. You get a runtime error, "Element already has a logical parent. It must be detached from the old parent before it is attached to a new one.".

using System;
using System.Windows;
using System.Windows.Controls;

namespace ReverseListbox
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ItemCollection items = this.listbox1.Items;
            for (int i = 0, j = items.Count - 1; i < j; i++, j--)
            {
                object tmpi = items[i];
                object tmpj = items[j];
                items.RemoveAt(j);
                items.RemoveAt(i);
                items.Insert(i, tmpj);
                items.Insert(j, tmpi);
            }
        }
    }
}

Here's the XAML for a complete sample:

<Window x:Class="ReverseListbox.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ListBox Name="listbox1" Grid.Row="0">
            <ListBoxItem Content="1" />
            <ListBoxItem Content="2" />
            <ListBoxItem Content="3" />
            <ListBoxItem Content="4" />
        </ListBox>
        <Button Name="button1" Grid.Row="1" Click="Button_Click" />
    </Grid>
</Window>
hughdbrown
A: 

I had a similar problem a while back. I ended up solving it similarly to Josh G's post but using a bit of encapsulation to avoid polluting the domain object.

See this discussion thread.

Another method that I use for collections that are only used by the UI (eg. log messages) is to simply insert them in reverse order in the first place, via collection.Insert(0, item);.

Miral