Background color of a ListBox item (Windows Forms)

94,404

Solution 1

Probably the only way to accomplish that is to draw the items yourself.

Set the DrawMode to OwnerDrawFixed and code something like this on the DrawItem event:

private void listBox_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    Graphics g = e.Graphics;

    g.FillRectangle(new SolidBrush(Color.Silver), e.Bounds);

    // Print text

    e.DrawFocusRectangle();
}

The second option would be using a ListView, although they have an other way of implementations (not really data bound, but more flexible in way of columns).

Solution 2

Thanks for the answer by Grad van Horck. It guided me in the correct direction.

To support text (not just background color), here is my fully working code:

//global brushes with ordinary/selected colors
private SolidBrush reportsForegroundBrushSelected = new SolidBrush(Color.White);
private SolidBrush reportsForegroundBrush = new SolidBrush(Color.Black);
private SolidBrush reportsBackgroundBrushSelected = new SolidBrush(Color.FromKnownColor(KnownColor.Highlight));
private SolidBrush reportsBackgroundBrush1 = new SolidBrush(Color.White);
private SolidBrush reportsBackgroundBrush2 = new SolidBrush(Color.Gray);

//custom method to draw the items, don't forget to set DrawMode of the ListBox to OwnerDrawFixed
private void lbReports_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();
    bool selected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected);

    int index = e.Index;
    if (index >= 0 && index < lbReports.Items.Count)
    {
        string text = lbReports.Items[index].ToString();
        Graphics g = e.Graphics;

        //background:
        SolidBrush backgroundBrush;
        if (selected)
            backgroundBrush = reportsBackgroundBrushSelected;
        else if ((index % 2) == 0)
            backgroundBrush = reportsBackgroundBrush1;
        else
            backgroundBrush = reportsBackgroundBrush2;
        g.FillRectangle(backgroundBrush, e.Bounds);

        //text:
        SolidBrush foregroundBrush = (selected) ? reportsForegroundBrushSelected : reportsForegroundBrush;
        g.DrawString(text, e.Font, foregroundBrush, lbReports.GetItemRectangle(index).Location);
    }

    e.DrawFocusRectangle();
}

The above adds to the given code and will show the proper text plus highlight the selected item.

Solution 3

// Set the background to a predefined colour
MyListBox.BackColor = Color.Red;
// OR: Set parts of a color.
MyListBox.BackColor.R = 255;
MyListBox.BackColor.G = 0;
MyListBox.BackColor.B = 0;

If what you mean by setting multiple background colors is setting a different background color for each item, this isn't possible with a ListBox, but it is with a ListView, with something like:

// Set the background of the first item in the list
MyListView.Items[0].BackColor = Color.Red;
Share:
94,404
BTHarris
Author by

BTHarris

Seasoned C#/Javascript Developer Im always working on something. github Contact me for more information. (Dested at Gmail)

Updated on July 09, 2022

Comments

  • BTHarris
    BTHarris almost 2 years

    How can I set the background color of a specific item in a System.Windows.Forms.ListBox?

    I would like to be able to set multiple ones if possible.

  • jfs
    jfs over 15 years
    It's possible with a ListBox. See stackoverflow.com/questions/91747/…
  • Matthew Scharley
    Matthew Scharley over 15 years
    s/possible/easy/. Oh well. C# 1, novice 0. I havn't worked much with overloading painting methods before.
  • Almo
    Almo over 12 years
    Excellent, the selected bit was very useful.
  • Prakash Vishwakarma
    Prakash Vishwakarma over 10 years
    What are reportsForegroundBrushSelected : reportsForegroundBrush ??
  • Prakash Vishwakarma
    Prakash Vishwakarma over 10 years
    reportsForegroundBrushSelected : reportsForegroundBrush gives me error, they're suppose to be declared but how?
  • Shadow The Kid Wizard
    Shadow The Kid Wizard over 10 years
    @PrakashVishwakarma done, see my edit. Thanks for the heads up, I also improved the overall efficiency, I was creating new Brush instance every call to the method which was wrong.
  • ghiboz
    ghiboz about 9 years
    the BackColor is not a property of ListBox.ObjectCollection item
  • Peter Mortensen
    Peter Mortensen almost 3 years
    An explanation would be in order. E.g, what is the idea/gist? Please respond by editing (changing) your answer, not here in comments (without "Edit:", "Update:", or similar - the answer should appear as if it was written today).
  • stigzler
    stigzler over 2 years
    Agreed with @PeterMortensen. Can't follow the logic of this at all - seems to miss the question quite badly. Lazy.
  • J. Chris Compton
    J. Chris Compton over 2 years
    This works great if you aren't going to scroll the listbox. It gets weird when I scroll, the items are all there - just the display is confused (highlight them and they paint correctly). VS 2022 & .NET Framework 4.8
  • Shadow The Kid Wizard
    Shadow The Kid Wizard over 2 years
    @J.ChrisCompton don't remember if I tested with scroll, but yeah this 11 years old code might have served its purpose already, lol. If you can find a way around it please let me know, and I can edit the answer with it.
  • J. Chris Compton
    J. Chris Compton over 2 years
    @ShadowWizardIsVaccinatedV3 Wanted to note for current/future users. I'm going to have to go with the ListView for now, I was just curious because I haven't seen a listbox solution like this. I may get a wild hair in the future and try to run it down - if I do, I'll post - but right now something working quickly is better than 'another interesting project'. Especially with OwnerDraw, which I have no prior experience with, and foresee no need of. ;-)
  • J. Chris Compton
    J. Chris Compton over 2 years
    I ran into this and wanted to post it. Works with .NET Framework (didn't test .Core) c-sharpcorner.com/article/… it does more stuff (icons in the listbox and right justifies the text). Something about the selection is a little off (seems to select with a boarder which isn't erased correctly until the listbox is scrolled). All very interesting to me, but little time to study it to figure out exactly what's wrong. Well, I'm at the end of my allowed number of characters so I suppose I have to end this long and rambling post... right... here.