[.net] sorting list box items

Started by
6 comments, last by Geronimo2000 17 years, 5 months ago
Hi, I've got a problem with sorting list box items. I have a list box in which I have custom items of various types. Each item derives from an abstract class which provide a Compare method and various other stuff. Now imagine I have 2 derived classes : A and B, and I add 10 items of each type in the list box. And now I'd like to sort the items by type (the first half of the list box will display all the items of type A, and the second half, the ones of type B) Here is the piece of code I'm using (and isn't working ^^) :

// the abstract class used for any items we want to store in the extended list box :
public abstract class IExtendedListBoxItem : IComparable<IExtendedListBoxItem>
{
    // a value used to sort various items types
    public int SortingValue = -1;

    // implement the IComparable.CompareTo method
    public int CompareTo(IExtendedListBoxItem obj)
    {
        return (obj.SortingValue - this.SortingValue);
    }

    // ... the rest of the code here
}


// the extended list box
public partial class ExtendedListBox : ListBox
{
    protected override void Sort()
    {
        if (this.Items.Count <= 1)
            return;

        // extract all the elements to an array
        IExtendedListBoxItem[] items = new IExtendedListBoxItem[this.Items.Count];
        this.Items.CopyTo(items, 0);

        // sort the array
        Array.Sort(items);

        // clear the items' list
        this.Items.Clear();

        // add the sorted elements
        foreach (Object obj in items)
            this.Items.Add(obj);
    }

    // ... the rest of the code here
}

The problem is that it's sorted by types ... but NOT in the specified order. Let's say I have items of type A to F, and the order will be A, C, B, F, E, D although I assigned A.SortingValue = 0 to F.SortingValue = F ... If someone knows how to do that, I'd appreciate a little help to understand what's going on :) Thx in advance
Advertisement
What you're trying to do is possible and should be easy. The way you described doing it seems like a pretty standard way of doing it. I can't see any problems with the code you posted. I'm assuming the problem could be in the code you didn't post.

Although, to be 100% honest with you, when I do something similar I always pass in an IComparer to the ListBox.Sort() function instead of overriding IComparable on the ListBox items, so I may be unaware of certain issues with your approach.
Hi,
thx for the reply.
You say you're passing an IComparer to ListBox.Sort() ? How do you do that ? I thought this method couldn't accept any parameter ? (at least in the documentation)
Do you mind telling me how you're doing ??

Thx again :)


Edit : ok, I did test something : I created a public method called MySort in which I copied the code that was in my first post (the one in ExtendListBox.Sort()) I also set the Sorted attribute to false. And when I call MyExtendListBox.Sort() it works perfectly !

As I understood it, when you set Sorted to true, each time you add an item to the listbox, it's inserted in the correct place, and the ListBox.Sort() method is only called when the Sorted attribute changes from false to true. The thing is, I don't know what sorting function it uses when you add a new item. And it's not the ListBox.Sort() :/ That's why I implemented IComparable : I thought that if I implemented it, it'd be used when adding an item to the listbox.


[Edited by - paic on November 17, 2006 3:30:59 AM]
Listbox uses its own sort function, your array list will be fine, but the listbox has it's own sort mechanism, derive from ListBox and override sort to do what you want.
Yep, I did that (overrided the ListBox.Sort() method) but it's only called once when Sorted is false and becomes true.
When I add a new item, it's not called, and the default sort is used instead (which uses the Object.ToString() method to alphabetically sort the items. And I'm looking for a way to override that behaviour so that when I add an item, it's sorted according to my desires.
Then call ListBox->Sorted = true; when needed.

EDIT: actually, what you were initially doing should be ok according to
http://msdn2.microsoft.com/en-us/library/system.windows.forms.listbox.sort(VS.80).aspx
but i'd think you have to set the sort property to false.. as essentially you're performing two sorts.
Ok, I found a solution to my problem : when you add an item to a listbox with "listbox.Items.Add(something);" (and with Sorted set to true) the listbox calls "something.ToString()" to insert "something" at the correct place in its items list.
And there is apparently no way to tell the listbox to use another value than the one returned by "ToString()" ... So I simply overrided the ToString method :

public abstract class IExtendedListBoxItem{    public override string ToString()    {        return this.SortingValue;    }    // the rest of the code ...}


This is not really clean, but at least it works fine : when Sorted is set to true, then the items are sorted depending on SortingValue (by the way, it's now a String)

[Edited by - paic on November 21, 2006 4:19:21 AM]
Just to clarify, there is obviously no ListBox.Sort() that takes an IComparer. I mistakenly typed that when what I really do is populate an ArrayList, and then call ArrayList.Sort() with an IComparer parameter, and then populate the ListBox with the ArrayList items.

It's pretty lame that ListBox.Sort() isn't called when an item is added.

This topic is closed to new replies.

Advertisement