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

Extending the ListBox to show more complex items

By , 4 Sep 2006
 

exListBox screenshot

Introduction

Ever wanted to have a lightweight list box control for your Windows Forms application to list custom items, for example, to list picture albums in a nice way - with an album front image, album name and details, like how many photos in an album, etc.? I was always disappointed with DataGridView, it's a good component in some cases, but usually you just need a nice, clear list, that's why I came up with this extended exListBox.

Background

I think everybody has noticed that the standard Windows Forms ListBox item is an object type, not a string. If you will try to pass your business object to ListBox.Items, it won't understand how you would like it to be displayed and will just print out your object's class name. But there's a solution - to override the OnDrawItem event, and placing your own drawing procedure. By the way, I was trying to keep the code as short as possible and as easy to understand as possible, so in that way, I didn't implemented real data binding, some constructors/properties aren't in the right places, and so on.

Using the code

There are two classes that you'll need - exListBox and exListBoxItem. The first one is derived from ListBox just to override the OnDrawItem event, though you could do this without creating a separate class, by simply handling the onDrawItem event in your form source code, but if you'll use the extended ListBox on several forms, it's better for sure to place the code on a separate code file. The second class (exListBoxItem) is created from scratch, it has its drawing procedure and the elements that need to show up on the list. On the current example, an item contains an image, item title, and item details, but you can easily extend exListBoxItem with your own code and have your own elements.

Adding new items is easy:

Image myImage = new Image.FromFile("image.jpg");
int id = 1;
myExListBox.Items.Add(new exListBoxItem(id, "title", "details", myImage));

As you can see, I've placed one more variable to exListBoxItem - id, it should help you bind exListBox with your databases. I didn't make any real data binding to keep the code small, easy to understand, and in an easy edit-to-fit-your-needs form.

ExListBoxItem selected = (myExListBoxItem)myExListBox.SelectedItem;
int id = selected.Id;

If you would like to change the fonts used in item drawing, or the image size, you should call the new constructor for your exListBox:

myExListBox = new exListBox(new Font(this.Font, FontStyle.Bold), 
              this.Font, new Size (100, 80), 
              StringAlignment.Near, StringAlignment.Near);

If you change the drawing procedure, you should take care of a few things. First of all, you need to check if the item which you will be drawing is selected or not. As you can see from the method title, I’m taking info about the selected item in DrawItemEventArgs. Here, I can find if the item is selected or not and the item bounds where I must draw the item. All other arguments are necessary only in my case. If your exListBoxItem contains other elements, it may look a bit different.

public void drawItem(DrawItemEventArgs e, Padding margin, 
       Font titleFont, Font detailsFont, StringFormat aligment, 
       Size imageSize)
{            

    if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
    {
        // if selected, mark the background differently
    }
    else
    {
        // mark as unselected or just don't make anything
    }

    // draw some item separator
    e.Graphics.DrawLine(Pens.DarkGray, e.Bounds.X, e.Bounds.Y, 
                        e.Bounds.X + e.Bounds.Width, e.Bounds.Y);

    // draw item elements

    ...
    // put some focus rectangle
    e.DrawFocusRectangle();
}

History

  • 1.0 - Article showed up.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

GiedriusBan
Lithuania Lithuania
Member
No Biography provided

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 5memberawttasarim9 Oct '12 - 2:19 
nice !
GeneralMy vote of 5mvpKanasz Robert27 Sep '12 - 11:07 
good
GeneralWonderful code, needs a small correctionmembercardigait11 Feb '10 - 23:33 
without DrawMode.OwnerDrawFixed on the listbox, the custom OnDrawItem does not activate.
It's logical but i lost some time, since i saw and older comment pointing this out.
 
However, saved my day, very useful and clear, tks!
GeneralAt lastmemberDimitris Mexis18 Oct '08 - 9:34 
At last someone who overrided the listbox behavior and shared the knowledge!
I google this thing two days now, and what I find is trash in comparison to your code, your details on OnDrawItem, onPaint, and how to draw with drawItem.
 
Bravo.
GeneralDrawModememberth3anvil11 Nov '07 - 17:29 
There is something that wasn't mentioned in this article and that I had trouble with for an hour or so...So I thought I'd share.
 
For the custom, owner drawn items to display correctly, the DrawMode on the listbox must be set to OwnerDrawFixed or OwnerDrawVariable.
 
Best of luck!
Jordan
QuestionCan you help me pleasememberrodcobalt2229 Nov '06 - 22:17 
I can't run your project demo or source. i can read your page that program is fmwk 1.0 (1.1 ?) but i can't execute. Sorry for my bad english.
SomeBody can helpe meD'Oh! | :doh:
 
rodcobalt22, vous salue bien

AnswerRe: Can you help me pleasememberGiedriusBan30 Nov '06 - 4:27 
it should work on 1.0 framework too, all you need to do is create empty project and using notepad copy paste my source to your empty project.
i think problem is, that i've created this project with VS2005 and VS2003 or older can't understand how to open it.
you can read about drawing listbox items by our own here:
http://msdn2.microsoft.com/en-us/library/system.windows.forms.listbox.objectcollection.aspx
GeneralRe: Can you help me pleasememberrodcobalt2230 Nov '06 - 5:14 
Thank for your answer but, even if i cut and paste your file in new project.
Any error show me by VS2003.
May be can you compil and share your controls but from VS 2003.
Your listBox is very interesante for me and i want to update for use in my project.
Thx.
Rodcobalt22
 
rodcobalt22, vous salue bien

Generalquestion... [modified]memberTheCardinal18 Oct '06 - 11:06 
how do you remove items from the list?
 
how to get the index of the current selected item?
is there a way of getting the current title, or detailtitle from the list.
 

-- modified at 17:11 Wednesday 18th October, 2006
GeneralWhy This ? [modified]memberThe Monz4 Sep '06 - 23:05 
Nice job, but one question...
 
Using : ListBox.Controls.Add() .. you could add you own userControl...
 
Piece of code like this could do the stuff
 
void CreateListBox()
{
for(int i = 0; i < 10; i ++)
{
Button btn = new Button();
btn.Size = new Size(50,20);
btn.Location = new Point(0,i * btn.Height);
ListBox1.Controls.Add(btn);
}
}
 

Am I wrong ?
 
Using this technic, you don't have to create a special ListBox but just
have to create your UserControl representing what you need...
 
Advantage : You could have different kind of control in your ListBox instead
of one dedicated to your wishes Wink | ;)
 
Or As you said, you could also have done stuff like this :
 
void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index >= 0)
{
Control toto = listBox1.Items[e.Index] as Control;
if (toto != null)
{
Bitmap map = new Bitmap(toto.Width, toto.Height);
toto.DrawToBitmap(map, new Rectangle(0, 0, toto.Width, toto.Height));
e.Graphics.DrawImage(map, new Point(e.Bounds.Left, e.Bounds.Top));
}
}
else
{
e.Graphics.FillRectangle(new SolidBrush(Color.Blue),e.Bounds);
}
}
 
This code will let you the ability to add any kind of control into your list box.. But, be aware that you won't be able to click on them and let them handle the click (ex : add a button as an item, define click event for the button, it won't be reached when selecting the button through the listbox)...
 
If I had to do kind of control like this, I'll maybe will prefer a Panel
with AutoScroll property Set to yes... and use Controls.Add(..) to be able
to handle a collection of Usercontrol for instance...
 
THe Monz, Toulouse, France
 

-- modified at 3:09 Wednesday 6th September, 2006
QuestionMax height of itemsmemberDenhomer4 Sep '06 - 22:40 
Is there a way to set the item height to anything bigger than 255 ?
I've noticed this behaviour in many listboxes.
As far as i know it's related to windows using only 1 byte to store the height, but i would really like to overwrite this height somehow.

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.130516.1 | Last Updated 4 Sep 2006
Article Copyright 2006 by GiedriusBan
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid