OwnerDrawn listboxes and DataSource - too many bad code examples....

I've seen a lot of examples out in the ether for OwnerDrawn listboxes and comboboxes that do something like:

private void mylistbox_DrawItem(object sender, DrawItemEventArgs e)
{
       e.DrawBackground();
       DataRowView rv = (DataRowView) mylistbox.Items[e.Index];
       string textToDisplay = rv[mylistbox.DisplayMember].ToString();
       e.Graphics.DrawString(textToDisplay, e.Font, new SolidBrush(e.ForeColor), e.Bounds.Location);
       e.DrawFocusRectangle();
}

While there are several problems with this little example the one I'm talking about is the extraction of the DataRowView from the items to get the string value of the display member. Not only does this require direct knowledge of the DataSource, which may or may not be what you're expecting, but it's also completely unneeded. The base class for ListBoxes and ComboBoxes, ListControl supports extracting the bound text from the DataSource object natively using the GetItemText() method. Here is a better implementation of DrawItem, one that will be flexible for any DataSource:

private void GenericDrawItemHandler(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
       ListBox thisBox = (ListBox) sender;

       // Draw the background of the ListBox control for each item.
       // equivalent to e.DrawBackground(); but shown here to demo
       // how to change color of the background easily
       using(Brush backBrush = new SolidBrush(e.BackColor))
       {
              e.Graphics.FillRectangle(backBrush, e.Bounds); 
       }

       // Draw the text. Use GetItemText to obtain the text from the DataSource
       using(Brush foreBrush = new SolidBrush(e.ForeColor))
       {
              e.Graphics.DrawString(thisBox.GetItemText(thisBox.Items[e.Index]), 
                     e.Font, foreBrush, e.Bounds, StringFormat.GenericDefault);
       }

       // Draw the focus rectangle of the ListBox if showing focus, 
       // and this cell is in focus.
       // equivalent to e.DrawFocusRectangle(); but shown here to demo
       // how to change color of the focus rectangle easily
       if (((e.State & DrawItemState.Focus) == DrawItemState.Focus) && 
              ((e.State & DrawItemState.NoFocusRect) != DrawItemState.NoFocusRect))
       {
              ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, e.ForeColor, e.BackColor);
       }
}

Hope it helps someone.....

-Andy

Print | posted on Tuesday, March 22, 2005 2:17 PM

Comments on this post

# re: OwnerDrawn listboxes and DataSource - too many bad code examples....

Requesting Gravatar...
Yep, this helped alot. Thanks man :)
Left by AndreasR on Oct 07, 2005 7:53 AM

# re: OwnerDrawn listboxes and DataSource - too many bad code examples....

Requesting Gravatar...
Hi,
I heva a question about your example code and many others...
if the dimension of the item text if bigger than "visible" listbox the item text is cut, how can I work around it?
Thanks in advance,
Sandrokan55
Left by sandro on May 29, 2006 12:43 PM

Your comment:

 (will show your gravatar)
 
Please add 7 and 3 and type the answer here: