Click here to Skip to main content
Click here to Skip to main content

Ordered ListBox

By , 29 Jul 2002
 

Overview

The OrdListBox is a class derived from System.Windows.Forms.ListBox and was written by me when I was working on a project where I had this requirement of having ordered items in a list box. The issue was that there might be multiple copies of the same item in the list box and I had no way to differentiate among these duplicate items. The duplicate items would obviously be textual abstractions of distinct underlying objects. MFC had CListBox::SetItemData which allowed us to associate a 32 bit value with an item in the list box. I assumed rather enthusiastically that there would be something analogous to that in the .NET ListBox class. It was with an intense annoyance that I realized that I couldn't find anything to do the job. Of course for all I know there might be some hidden feature somewhere which I had overlooked and missed. But anyway I had to write my own class to achieve what I wanted to. I was a little stuck when Shog9 brilliantly helped me out with a beautiful but simple suggestion that I totally missed out on.

Purpose

The class basically allows you to associate strings with each list box item. Now when you add an item to the string using the new method added to the derived class, this order string will be used to determine the position where this new item would be inserted at. The order string can be either numeric or non-numeric. If the order string is numeric then 6 comes before 12, but if the order string is non-numeric you must watch out, because 6 is now greater than 12 on account of it's position in the character set.

Sample Usage

//...

/* Create a new OrdListBox with numeric order */
OrdListBox listBox1 = new OrdListBox(true);

//...

/* You must use this method to add items to the 
 list box. Because if you use ListBox methods
 to add items, the class will obviously fail!  */
listBox1.AddOrderedItem(textBox1.Text,textBox2.Text);

//...

/* You can call ListBox methods too */
listBox1.Items.RemoveAt(listBox1.SelectedIndex);

//...

/* GetItemOrder can be used to return the order */
MessageBox.Show(
    listBox1.GetItemOrder(listBox1.SelectedIndex),
    listBox1.Items[listBox1.SelectedIndex].ToString());

//...

Function Reference

Constructor

Initializes a new instance of the OrdListBox class.

public OrdListBox( bool bNum );

  • bNum - Set this to true to make the ordering numeric and to false to make the ordering non-numeric.

AddOrderedItem

This will add a new ordered item to the ordered  list box, and it will insert the new item at the correct position within the list box, that will maintain the order of the items in the list box, after the new item has been added to it.

public void AddOrderedItem(string ItemText, string ItemOrder);

  • ItemText - This is the text of the item to be added to the ordered list box.
  • ItemOrder - This is the order string that will specify the order value of the item to be added.

GetItemOrder

This method will return the order value of an item in a list box given the index of the item within the list box.

public string GetItemOrder(int index)

  • index - This is the index of the required item within the list box.

Return Value

The method will return a string that represents the order value of the specified list box item.

Code Listing

public class OrdListBox : System.Windows.Forms.ListBox
{

    public OrdListBox(bool bNum)
    {
        bNumeric = bNum;
        Sorted = false; //required
    }

    public void AddOrderedItem(string ItemText, string ItemOrder)
    {
        ItemData data = new ItemData(ItemText,ItemOrder);
        int c = Items.Count;    

        /* Loop through list box and locate 
         point of insertion */
        for (int i = 0; i < Items.Count; i++)
        {
            if (data.IsLess((ItemData)Items[i],bNumeric))
            {
                //Found! Now insert
                Items.Insert(i,data);
                break;
            }
        }           
        if( c == Items.Count)
        {               
            //Missed out, so insert at end.
            Items.Insert(c,data);
        }
    }

    public string GetItemOrder(int index)
    {
        if(index < 0 || index >= Items.Count)
            return null;
        else
            return ((ItemData)Items[index]).ItemOrder;
    }

    private bool bNumeric = false;

    /* Inner class which defines the object that 
     we insert as a list box item */
    class ItemData
    {
        public ItemData(string str1, string str2)
        {
            m_ItemText=str1;
            m_ItemOrder=str2;
        }
        private string m_ItemText;
        private string m_ItemOrder;

        /* Required for list box display purposes */
        public override string ToString()
        {
            return m_ItemText;
        }

        /*
          This method figures out whether the instance object
          is less than the given object. It does this in two 
          different ways depending on whether the order
          has been set to numeric or non-numeric
        */
        public bool IsLess(ItemData d, bool bNum)
        {
            if(bNum)
            {
                int i1 = Convert.ToInt32(m_ItemOrder);
                int i2 = Convert.ToInt32(d.m_ItemOrder);
                return ( i1 < i2 );
            }
            else
            {
                return ( m_ItemOrder.CompareTo(d.m_ItemOrder) < 0 );
            }
        }

        public string ItemOrder
        {
            get
            {
                return m_ItemOrder;
            }
        }
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Nish Sivakumar
United States United States
Member
Nish is a real nice guy who has been writing code since 1990 when he first got his hands on an 8088 with 640 KB RAM. Originally from sunny Trivandrum in India, he has been living in various places over the past few years and often thinks it’s time he settled down somewhere.
 
Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com.
 
Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book – Extending MFC applications with the .NET Framework.
 
Nish's latest book C++/CLI in Action published by Manning Publications is now available for purchase. You can read more about the book on his blog.
 
Despite his wife's attempts to get him into cooking, his best effort so far has been a badly done omelette. Some day, he hopes to be a good cook, and to cook a tasty dinner for his wife.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5mvpKanasz Robert27 Sep '12 - 11:05 
good job Wink | ;)
Generalallow user to enter other itemmemberburgekurt21 Aug '04 - 5:12 
Hello,
 
I want to create a combobox which has also an OTHER item and when someone selects this item, i want to open a textbox and get the item by this way. How can i do this? I haven´t got any experience in c# Frown | :(
 
Best,
Burge
GeneralStill has the same problem as mine...membertheRealCondor24 Oct '02 - 8:50 
Eek! | :eek:
 
We had a project where we had to do sorted listboxes as well.
Our first approach was inline code which was initiated by clicking the 'Add' button. I later looked into building a sorted listbox and ended up with similar code. In doing so, I built an overloaded method AddSorted to the control which has the same parameters as Items.Add.....namely
AddSorted(System.Web.UI.WebControls.ListboxItem Item){}
AddSorted(string Item){}
 
My control, however, suffered the same weakness yours does: the method for adding items still exists. The re-order function is a workaround, but I continued to seek out alternatives. To do a "proper" implementation, I would add a property Sorted which is a boolean that has a default of False. Then "all I had to do" was override the Items.Add method and have my code locate the position for the add if Sorted=true, or let base.Add execute asis if Sorted=false. But I struggled with the biggest block MS created in the design of the default controls:
 
Add is a method of System.Web.UI.WebControls.ListItemCollection which is a collection of ListItem's. It would be best to be able to do :
public void SortedListItemCollection : ListItemCollection
...
public void Add(ListItem item)
{
if (bmSortedProperty == true)
...
else
base.Add(item)
}
 
Then overload Item with SortedListItemCollection. Unfortunately, both the ListItem and ListItemControl are marked NOTINHERITABLE!!!!! Have you done any figuring yet to determine a way to 'fully' integrate the sorted listbox into the control at all?
 
Still stumped in my custom control

GeneralJust some little things...sussAnonymous30 Jul '02 - 23:19 
Hi,
 
First of all, fine article Smile | :)
 
Well, i was just wondering...
U need some ordered items... ok..
Why don't u put objects themselves instead of string?
 
Then with
//Move down an object in the ItemList. Return new index of this object
public int MoveDown(object objectToMoveDown)
{
if (this.Items.Contains(objectToMoveDown))
{
int index=this.Items.IndexOf(objectToMoveDown);
if (index0)
{
this.Items.Remove(objectToMoveUp);
this.Items.Insert(index-1,objectToMoveUp);
return index-1;
}
else
{
return 0;
}
}
else
{
return -1;
}
}
...u can easily order your items...
If u want an abstraction, you could encapsulate your object into another with :
public class StringAbstraction
{
public object objectEncapsulated;
 
public StringAbstraction()
{
}
 
public override string ToString()
{
return (MyRealObjectEncapsulatedClass)objectEncapsulated.StringRepresentation();
}
}
 
and then add those items to the listBox instead of string
 
The order is known by the ItemList (and then listBox),it's the itemIndex...
 
Am i wrong?
GeneralRe: Just some little things...editorNishant S30 Jul '02 - 23:42 
Thanks for your comments. The class was written to suite my immediate requirements. The class can be modified to fit any other requirements that arise. For example you have asked why it takes strings instead of objects, but it's quite easy to modify the class to accept objects instead of strings. Just make 2-3 changes in the code. Thanks once again.
 
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

GeneralRe: Just some little things...sussAnonymous26 Jan '03 - 8:42 
I think the point is that the combo and listbox already accept objects, so there is no need for any extra code. The ".Item" property is an object, so just put your object in the list instead of your string, and tell the listbox to use whatever property the object contains that has your string, or override the tostring property of your object to return whatever you want to show in the list, and the listbox will figure it out for you.
QuestionAre you god?memberStefan Spenz30 Jul '02 - 4:19 
Nish, you must have read my mind, that is EXACTLY one of the stuff I need in my current project... OMG | :OMG:
 
Thx man! Smile | :)
 
When I was young my mother told me to clean up my room, I told her -1!
AnswerRe: Are you god?editorNishant S30 Jul '02 - 4:25 
Stefan Spenz wrote:
Nish, you must have read my mind, that is EXACTLY one of the stuff I need in my current project...
 
Dear Stefan,
 
Thanks Smile | :)
 
By the way, I have been trying to update the download-zip and the screenshot image, but there is a script error and I have been unable to do that so far. I have mailed Chris M about it.
 
So would you like me to email you the updated zip-file of the demo project? The current zip does not demonstrate the MoveUp and MoveDown features and there is also a slight issue with the C# form designer. These issues have been solved in the new zip file.
 
I can email it to you now itself.
 
Regards,
Nish
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

AnswerRe: Are you god?editorNishant S30 Jul '02 - 4:39 
Stefan Spenz wrote:
Thx man!
 
w00t
 
Yippeeeeeeee! Problem solved Smile | :)
 
I have updated both zip and screenshot.
 
You might have to hit Ctrl-Refresh to refresh the image.
 
Nish Jig | [Dance]
 

Author of the romantic comedy

Summer Love and Some more Cricket [New Win]

Review by Shog9
Click here for review[NW]

AnswerRe: Are you god?memberTweety30 Jul '02 - 4:59 
Stefan Spenz wrote:
Are you god?
 
He is not GOD. But I guess sometimes he looks like a greek GOD !
 
Tweety
 
It's easy to sit there and say you'd like to have more money. And I guess that's what I like about it. It's easy. Just sitting there, rocking back and forth, wanting that money.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 30 Jul 2002
Article Copyright 2002 by Nish Sivakumar
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid