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