Reputation: 53
Looking for a simple way to add color text (or bold text) to a listbox item (the solutions I've seen in Stackoverflow have seemed overly complicated for my needs).
I've been adding comments to my listbox via this code:
listBox1.Items.Add("Test complete!");
This line is peppered throughout my code. I'd love to be able to modify the occasional text with color such that a line like "Test complete!" shows up in green.
Is there a simple, on-the-fly solution to this?
Upvotes: 3
Views: 12507
Reputation: 1493
You can but takes a little a bit of work to setup, not really that complicated if you are just looking to setup the font color or font.
You have to add a handler to the DrawItem event.
this.listBox1.DrawItem += new DrawItemEventHandler(listBox1_DrawItem);
and here is a pretty simple handler that does what you are looking for.
void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
Graphics g = e.Graphics;
Dictionary<string, object> props = (this.listBox1.Items[e.Index] as Dictionary<string, object>);
SolidBrush backgroundBrush = new SolidBrush(props.ContainsKey("BackColor") ? (Color)props["BackColor"] : e.BackColor);
SolidBrush foregroundBrush = new SolidBrush(props.ContainsKey("ForeColor") ? (Color)props["ForeColor"] : e.ForeColor);
Font textFont = props.ContainsKey("Font") ? (Font)props["Font"] : e.Font;
string text = props.ContainsKey("Text") ? (string)props["Text"] : string.Empty;
RectangleF rectangle = new RectangleF(new PointF(e.Bounds.X, e.Bounds.Y), new SizeF(e.Bounds.Width, g.MeasureString(text, textFont).Height));
g.FillRectangle(backgroundBrush, rectangle);
g.DrawString(text, textFont, foregroundBrush, rectangle);
backgroundBrush.Dispose();
foregroundBrush.Dispose();
g.Dispose();
}
and then to add items to the ListBox you can do this.
this.listBox1.Items.Add(new Dictionary<string, object> { { "Text", "Something, something"},
{ "BackColor", Color.Red },
{ "ForeColor", Color.Green}});
this.listBox1.Items.Add(new Dictionary<string, object> { { "Text", "darkside!!" },
{ "BackColor", Color.Blue },
{ "ForeColor", Color.Green },
{ "Font", new Font(new Font("Arial", 9), FontStyle.Bold) } });
Fairly simple I think.
Upvotes: 5
Reputation: 9571
There's no way to do with without drawing the items in the ListBox
yourself. However, this isn't hard to accomplish with code. A trivial implementation that assumes the items aren't removed/reordered in the list box involves just keeping a dictionary mapping an index to a color and then drawing it with something like this:
private void ListBox_DrawItem(object sender, DrawItemEventArgs e)
{
var isItemSelected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected);
Color foreColor;
if (!this.mColorsByIndex.TryGetValue(e.Index, out foreColor))
{
foreColor = isItemSelected ? SystemColors.HighlightText : this.mListBox.ForeColor;
}
var backColor = isItemSelected ? SystemColors.Highlight : this.mListBox.BackColor;
using (var backBrush = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(backBrush, e.Bounds);
}
var item = this.mListBox.Items[e.Index];
var itemText = this.mListBox.GetItemText(item);
const TextFormatFlags formatFlags = TextFormatFlags.Left | TextFormatFlags.VerticalCenter;
TextRenderer.DrawText(e.Graphics, itemText, e.Font, e.Bounds, foreColor, formatFlags);
}
In terms of custom drawing in WinForms
, this is almost as simple as it gets.
Note that ListBox.Items.Add
returns the index of the item you added.
Keeping up with the color associations gets a little harder if you remove/change/reorder items in the ListBox
, but that complicates tracking the color associations, not the drawing itself.
Upvotes: 0