none
ListBox item color

Answers

  • You'll need to store a property that indicates the item is marked.  That's easy enough to do with ListBox, it stores objects:

      public partial class Form1 : Form {
        public Form1() {
          InitializeComponent();
          listBox1.Items.Add(new MyListItem("one"));
          listBox1.Items.Add(new MyListItem("two"));
          listBox1.Items.Add(new MyListItem("nobugz"));
        }
        private class MyListItem {
          private string mText;
          private bool mMarked;
          public MyListItem(string txt) {
            mText = txt;
          }
          public bool Marked {
            get { return mMarked; }
            set { mMarked = value; }
          }
          public override string ToString() {
            return mText;
          }
        }
        private void MarkSelectedItem(bool on) {
          MyListItem item = listBox1.SelectedItem as MyListItem;
          if (item == null) return;
          item.Marked = on;
          listBox1.Refresh();
        }
        private void markToolStripMenuItem_Click(object sender, EventArgs e) {
          MarkSelectedItem(true);
        }
        private void unmarkToolStripMenuItem_Click(object sender, EventArgs e) {
          MarkSelectedItem(false);
        }
        private void listBox1_DrawItem(object sender, DrawItemEventArgs e) {
          MyListItem item = listBox1.Items[e.Index] as MyListItem;
          Color foreColor = e.ForeColor;
          // Special drawing only if the item is marked and not selected
          if ((e.State & DrawItemState.Selected) == DrawItemState.Selected || !item.Marked) {
            if (item.Marked) foreColor = Color.Red;  // Make it stand out as marked even when selected
            e.DrawBackground();
          }
          else {
            using (SolidBrush bbr = new SolidBrush(Color.Red))
              e.Graphics.FillRectangle(bbr, e.Bounds);
            foreColor = Color.White;
          }
          using (SolidBrush solidBrush = new SolidBrush(foreColor))
            e.Graphics.DrawString(item.ToString(), e.Font, solidBrush, e.Bounds, StringFormat.GenericDefault);
          e.DrawFocusRectangle();
        }
      }

    Note that you shouldn't use Blue as the background of a marked item, the selection highlight is blue too.
    Wednesday, August 15, 2007 5:55 PM

All replies

  •  

    It's possible, but you have to draw the string yourself.  See this post: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1996703&SiteID=1
    Wednesday, August 15, 2007 11:54 AM
  • There's a stupid bug in the MSDN code sample and it doesn't show you how to use the State property. Try this instead:

      public partial class Form1 : Form {
        public Form1() {
          InitializeComponent();
          this.listBox1.Items.AddRange(new object[] {"one", "two", "three", "four" });
          this.listBox1.DrawMode = DrawMode.OwnerDrawFixed;
          this.listBox1.DrawItem += listBox1_DrawItem;
        }

        private void listBox1_DrawItem(object sender, DrawItemEventArgs e) {
          Color fore = e.ForeColor;
          if ((e.State & DrawItemState.Selected) != DrawItemState.Selected) e.DrawBackground();
          else {
            using (SolidBrush bbr = new SolidBrush(Color.Red))
              e.Graphics.FillRectangle(bbr, e.Bounds);
            fore = Color.White;
          }
          using (SolidBrush fbr = new SolidBrush(fore))
            e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, fbr, e.Bounds, StringFormat.GenericDefault);
          e.DrawFocusRectangle();
        }
      }
    Wednesday, August 15, 2007 12:49 PM
  • Thanks,this really change the color of the selected item but my goal was different.Maybe my explanation for what i want to do was bad,sorry.I mean when i select another item in the ListBox i want to change it's forecolor/backcolor,but i do not want to happened automatically.I have a context menu to the ListBox and from this context menu the user can change the colors of the current selected item.In other words how to raise that DrawItem event when the user clicks on the context menu item?Or there is something else which i have to do?
    Wednesday, August 15, 2007 4:39 PM
  • Just call Refresh() to force the ListBox to be repainted.
    Wednesday, August 15, 2007 4:45 PM
  • Ok,but when i change the color with Refresh thaw would raise DrawItem event,right?I forgot to say that i want to keep the changing of colors when they are selected,but if the DrawItem is raised from the context menu item the color must be permanent.When the user change the color of the selected item through item in the context menu the item has to keep the color after next raising of DrawItem event(i.e. the next selection).I want some items(items on selection) with Gold BackColor for example,and others(items which user want to highlight) with Blue BackColor.

    In short:when user change item on the ListBox DrawItem must change the color of the new selected item and set the default color of the previous selected item.That's ok.But if user clicks on highlightItem the color must be permanent,i.e. not changed to default color after selecting another item.
    Code Snippet

     private void listBox_DrawItem(object sender, DrawItemEventArgs e)
         {
          Color foreColor = e.ForeColor;
          if ((e.State & DrawItemState.Selected) != DrawItemState.Selected) e.DrawBackground();
          else {
                  using (SolidBrush bbr = new SolidBrush(Color.Blue))
                  e.Graphics.FillRectangle(bbr, e.Bounds);
                  foreColor = Color.White;
          }
          using (SolidBrush solidBrush = new SolidBrush(foreColor))
            e.Graphics.DrawString(listBox.Items[e.Index].ToString(), e.Font, solidBrush, e.Bounds, StringFormat.GenericDefault);
          e.DrawFocusRectangle();
        }

            private void highlightItem_Click(object sender, EventArgs e)
            {

               //when the DrawItem is raised from here i want permanent color on the item

               listBox.Refresh();
            }


    Sorry for the bad english,i don't know whether i use the word "permanent" correctly.I hope you will understand what i want to achieve.
    Wednesday, August 15, 2007 5:30 PM
  • You'll need to store a property that indicates the item is marked.  That's easy enough to do with ListBox, it stores objects:

      public partial class Form1 : Form {
        public Form1() {
          InitializeComponent();
          listBox1.Items.Add(new MyListItem("one"));
          listBox1.Items.Add(new MyListItem("two"));
          listBox1.Items.Add(new MyListItem("nobugz"));
        }
        private class MyListItem {
          private string mText;
          private bool mMarked;
          public MyListItem(string txt) {
            mText = txt;
          }
          public bool Marked {
            get { return mMarked; }
            set { mMarked = value; }
          }
          public override string ToString() {
            return mText;
          }
        }
        private void MarkSelectedItem(bool on) {
          MyListItem item = listBox1.SelectedItem as MyListItem;
          if (item == null) return;
          item.Marked = on;
          listBox1.Refresh();
        }
        private void markToolStripMenuItem_Click(object sender, EventArgs e) {
          MarkSelectedItem(true);
        }
        private void unmarkToolStripMenuItem_Click(object sender, EventArgs e) {
          MarkSelectedItem(false);
        }
        private void listBox1_DrawItem(object sender, DrawItemEventArgs e) {
          MyListItem item = listBox1.Items[e.Index] as MyListItem;
          Color foreColor = e.ForeColor;
          // Special drawing only if the item is marked and not selected
          if ((e.State & DrawItemState.Selected) == DrawItemState.Selected || !item.Marked) {
            if (item.Marked) foreColor = Color.Red;  // Make it stand out as marked even when selected
            e.DrawBackground();
          }
          else {
            using (SolidBrush bbr = new SolidBrush(Color.Red))
              e.Graphics.FillRectangle(bbr, e.Bounds);
            foreColor = Color.White;
          }
          using (SolidBrush solidBrush = new SolidBrush(foreColor))
            e.Graphics.DrawString(item.ToString(), e.Font, solidBrush, e.Bounds, StringFormat.GenericDefault);
          e.DrawFocusRectangle();
        }
      }

    Note that you shouldn't use Blue as the background of a marked item, the selection highlight is blue too.
    Wednesday, August 15, 2007 5:55 PM