Use a custom sort order for ListBox or ComboBox items in C#

[custom sort order]

If you set a ComboBox and ListBox control’s Sorted property to true, the control sorts the items it contains. Unfortunately it sorts the items alphabetically. That means if the items are strings that begin with Roman numerals, they may be out of order. For example, alphabetically IX (10) comes before V (5) and C (100) comes before X (10).

The example Make extension methods that convert to and from Roman numerals in C# shows how to make an extension method to parse Roman numerals. This example uses that extension method to provide a custom sort order for a ListBox and a ComboBox so they sort their by Roman numeral prefixes.

The program uses the following comparer class to provide the custom sort order.

class RomanItemComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        // Get the value of the leading Roman numerals.
        int xarabic = GetRomanValue(x);
        int yarabic = GetRomanValue(y);

        // Compare them.
        return xarabic.CompareTo(yarabic);
    }

    // Get the value of the value's leading Roman numeral.
    private int GetRomanValue(string value)
    {
        try
        {
            int pos1 = value.IndexOf('.');
            string roman = value.Substring(0, pos1);
            return roman.ToArabic();
        }
        catch
        {
            return 0;
        }
    }
}

The class implements IComparable<string> so it must provide a Compare method that compares two string objects.

This class’s Compare method calls the GetRomanValue method to get the value of the Roman numeral at the beginning of the two string objects. It compares them and returns the result.

The GetRomanValue method assumes the strings begin with a Roman numeral value followed by a period. It find the period, extracts the substring before it containing the Roman numeral, and uses the ToArabic extension method from the previous post to convert the result into an integer. If anything goes wrong, GetRomanValue returns 0 so values that don’t contain Roman numerals go at the beginning of the sorted list.

The main program uses the following code to sort the items in two of its ListBox and ComboBox controls.

private void Form1_Load(object sender, EventArgs e)
{
    // Copy the items into an array.
    int num_items = lstNumeric.Items.Count;
    string[] items = new string[num_items];
    for (int i = 0; i < num_items; i++)
        items[i] = lstNumeric.Items[i].ToString();

    // Sort the array.
    RomanItemComparer roman_comparer =
        new RomanItemComparer();
    Array.Sort(items, roman_comparer);

    // Display the sorted items.
    lstNumeric.Sorted = false;
    lstNumeric.DataSource = items;
    cboNumeric.Sorted = false;
    cboNumeric.DataSource = items;

    // Sort the alphabetically sorted controls.
    lstAlphabetic.Sorted = true;
    cboAlphabetic.Sorted = true;

    lstAlphabetic.SelectedIndex = -1;
    cboAlphabetic.SelectedIndex = -1;
    lstNumeric.SelectedIndex = -1;
    cboNumeric.SelectedIndex = -1;
}

This code copies the lstNumeric control’s items into an array. It makes a RomanComparer and passes it and the array into the Array.Sort method to sort the items by their Roman numeral values.

The code then makes the lstNumeric and cboNumeric controls display the sorted data.

You can use a similar technique to display items in other sort orders. Make a comparer class to compare items for the custom sort order, sort the items, and then display the sorted results.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in algorithms, controls, user interface and tagged , , , , , , , , , , , , , , , . Bookmark the permalink.

2 Responses to Use a custom sort order for ListBox or ComboBox items in C#

  1. WouterH says:

    There is also a dirty way: you can override the private comparer member of the ObjectCollection ComboBox.Items and assign your own IComarer instance to it.

  2. Rod Stephens says:

    I don’t think I would call that the dirty way. That’s a more flexible approach.

Leave a Reply

Your email address will not be published. Required fields are marked *