Link to home
Start Free TrialLog in
Avatar of dfins
dfinsFlag for United States of America

asked on

Changing Colors of individual Items in ComboBox in VS2005 / C#

Hey guys,
 
     I've got a SQL query that's dumping a bunch of data to me. As I parse through the records, I've got a list of items that I would like to distinguish between one another. For example, some items I would like to be red, others I would like to be green.

I've looked all over the internet, and the best examples I've found don't do anything else other than showing me how to change the colors based on if all of the data was pre-populated into an array, and that the text matched up with color names, for example.

This won't help me because I will only know what colors I want that individual item to be at the moment that I do my "comboBox.Items.Add" command.


This is the best code that I can find, but as you can see, it's event driven, which doesn't help me much because I have no way of passing pertinant "CASE / SWITCH" information to this event driven procedure. So it really doesn't help me at all...

Any idea how I can do this?



private void Form1_Load(object sender, System.EventArgs e)  
{  
   comboBox2.Items.Add("Item 1");  
   comboBox2.Items.Add("Item 2");  
   comboBox2.Items.Add("Item 3");  
}  
 
private void comboBox2_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)  
{  
Graphics g = e.Graphics ;  
 
if ( e.Index == 1 )    
{  
   SolidBrush b = (SolidBrush)new SolidBrush(Color.Black);  
   e.Graphics.DrawString(b.Color.Name, new Font("Veranda", 12, FontStyle.Bold), new SolidBrush(Color.Red), e.Bounds);  
   e.DrawFocusRectangle();  
}  
 
if (e.Index == 2)  
{  
   SolidBrush b = (SolidBrush)new SolidBrush(Color.Red);  
   e.Graphics.DrawString(b.Color.Name, new Font("Veranda", 12, FontStyle.Bold), new SolidBrush(Color.Yellow), e.Bounds);  
   e.DrawFocusRectangle();  
}  
 
if (e.Index == 3)  
{  
   SolidBrush b = (SolidBrush)new SolidBrush(Color.Firebrick);  
   e.Graphics.DrawString(b.Color.Name, new Font("Veranda", 12, FontStyle.Bold), new SolidBrush(Color.Silver), e.Bounds);  
   e.DrawFocusRectangle();  
}  
Avatar of Jaime Olivares
Jaime Olivares
Flag of Peru image

Which criteria do you want to evaluate?
How are you filling your data into your control?
Avatar of dfins

ASKER

Well, the criteria of what I'm evaluating isn't of any signifigance, at least to this example, but basically... for each record in my query, I run a check, like for example, if this one field... if the Boolean is set to TRUE, then I want the text that I put into my ComboBox for that item to be RED, for example, otherwise I want it to be BLACK.

I'm filing it in right now by doing ComboBox.Items.Add("current record goes here");
Create a class or struct as:
public class ComboItem
{
     public string str;
     public Color color;

     public ComboItem(string _str, Color _color)
     {
          str = _str;
          color = _color;
     }
     public override string ToString()
     {
          return this.str;
     }
}

Then evaluate your criteria as you want and determine some color in a variable. Finally add the item to the combo as:
yourCombo.Items.Add(new ComboItem(yourStr, yourColor));
Everything should work as usual, but now you can know the color when painting:
private void comboBox2_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)  
{
   SolidBrush b = (SolidBrush)new SolidBrush((e.Item as ComboItem).color);  
   e.Graphics.DrawString(e.Item.ToString(), controlFont, b, e.Bounds);  
   e.DrawFocusRectangle();    
}

notice there is a "controlFont" variable. Define it as a form's member as:
public Font controlFont = new Font("Veranda", 12, FontStyle.Bold)
 so you don't have to create it every time you need it.
Avatar of dfins

ASKER

Thanks Jamie, this is awesome... so close... the only problem is that I get an error:

Error      'System.Windows.Forms.DrawItemEventArgs' does not contain a definition for 'Item'

Any idea what I should use instead for item? I got pretty far awhile back, and then ran into this same problem.

Thank you for helping me!
Sorry, writing from my memory, replace the drawitem method with
private void comboBox2_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)  
{
   ComboItem item = comboBox2.Items[e.Index] as ComboItem;
   SolidBrush b = (SolidBrush)new SolidBrush(item.color);  
   e.Graphics.DrawString(item.str, controlFont, b, e.Bounds);  
   e.DrawFocusRectangle();    
}
Avatar of dfins

ASKER

Thank you so much! I'm ALMOST there... the ONLY problem Ihave is that I get this error:

InvalidArgument=Value of '-1' is not valid for 'index'.
Parameter name: index

Any idea? I don't know why it would be set to -1? I add the items on Form-Load...
It is unrelated to my proposal. I guess the -1 comes from some code where you are trying to use your color criteria.
-1 means that an IndexOf() method didn't find an expected string. Maybe you can post some code around,.
 
Avatar of dfins

ASKER

Thanks Jaime, below is actually the entire application.

I built a small application to test the code before I moved it to my actual application. I get the same error:


VS2005 / C#


 
 
-----------------------------------------------------------------------------------------------------------------
 

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace MyComboBox
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.ComboBox comboBox2;
private System.ComponentModel.Container components = null;
public Font controlFont = new Font("Veranda", 12, FontStyle.Bold);
 
 
public Form1()
{
InitializeComponent();
}
 
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
 
private void InitializeComponent()
{
this.comboBox2 = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// comboBox2
//
this.comboBox2.BackColor = System.Drawing.SystemColors.ActiveCaptionText;
this.comboBox2.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBox2.ItemHeight = 20;
this.comboBox2.Items.AddRange(new object[] {
"Please select a player..."});
this.comboBox2.Location = new System.Drawing.Point(12, 12);
this.comboBox2.Name = "comboBox2";
this.comboBox2.Size = new System.Drawing.Size(288, 26);
this.comboBox2.TabIndex = 0;
this.comboBox2.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.comboBox2_DrawItem);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(312, 157);
this.Controls.Add(this.comboBox2);
this.Name = "Form1";
this.Text = "OwnerDraw ComboBox";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
static void Main()
{
Application.Run(new Form1());
}
 
 
 
private void Form1_Load(object sender, System.EventArgs e)
{
comboBox2.Items.Add(new ComboItem("Item 1", Color.Red));
comboBox2.Items.Add(new ComboItem("Item 1", Color.Red));
comboBox2.Items.Add(new ComboItem("Item 1", Color.Red));
comboBox2.Items.Add(new ComboItem("Item 1", Color.Red));
}
private void comboBox2_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
ComboItem item = comboBox2.Items[e.Index] as ComboItem;
SolidBrush b = (SolidBrush)new SolidBrush(item.color);
e.Graphics.DrawString(item.str, controlFont, b, e.Bounds);
e.DrawFocusRectangle();
}
}
public class ComboItem
{
public string str;
public Color color;
public ComboItem(string _str, Color _color)
{
str = _str;
color = _color;
}
public override string ToString()
{
return this.str;
}
}
 
}
ASKER CERTIFIED SOLUTION
Avatar of Jaime Olivares
Jaime Olivares
Flag of Peru image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dfins

ASKER

I made a couple of tweaks to it, but that was the answer, and now it works!!!!
 
 
See code:
 

static void Main()
{
Application.Run(new Form1());
}
 
 
 
private void Form1_Load(object sender, System.EventArgs e)
{
comboBox2.Items.Add(new ComboItem("Item 1", Color.Red));
comboBox2.Items.Add(new ComboItem("Item 1", Color.Red));
comboBox2.Items.Add(new ComboItem("Item 1", Color.Red));
comboBox2.Items.Add(new ComboItem("Item 1", Color.Red));
}
private void comboBox2_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
if (e.Index > 0)
{
ComboItem item = comboBox2.Items[e.Index] as ComboItem;
SolidBrush b = (SolidBrush)new SolidBrush(item.color);
e.Graphics.DrawString(item.str, controlFont, b, e.Bounds);
e.DrawFocusRectangle();
}
}
}
public class ComboItem
{
public string str;
public Color color;
public ComboItem(string _str, Color _color)
{
str = _str;
color = _color;
}
public override string ToString()
{
return this.str;
}
}  
Avatar of dfins

ASKER

See final code in last post.
about this:
>>if (e.Index > 0)

index could be 0, so I guess it should be:
if (e.Index >= 0)
 
Avatar of dfins

ASKER

Hah... thanks! You're right!!!
By the way, I really appreciate the help!!! You saved me tons of hours of anguish...