Laden...

ListBox mit verschiedenen Farben (Hintergrund oder Text)?

18 Antworten
17,682 Aufrufe
Letzter Beitrag: vor 13 Jahren
ListBox mit verschiedenen Farben (Hintergrund oder Text)?

Hi,

wie kann ich in einer ListBox meinen Elementen verschiedene Farben zuordnen?
Egal ob jetzt der Text oder der Hintergrund anderst ist.
Sinn der Sache:
Ein Userliste: User Online -> Grün; User Offline -> Rot.

Hi,
muss das eine ListBox sein?
ListView-Items kannst du Farben zuweisen:


lvi = new ListViewItem("Text" , 0, Color.Black, Color.Rot, font);
this.ListView1.Items.Add(lvi);

der Code macht die Schriftfarbe Schwarz, den Hintergrund Rot.

Wenn es eine ListBox sein soll, dann muss man selber eine machen....


using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace ColorListBox
{
	/// <summary>
	/// Summary description for ColorListBox.
	/// </summary>
	public class ColorListBox : ListBox 
	{
		public ColorListBox():base()
		{
			//Default auf OwnerDrawFixed setzen
			base.DrawMode=DrawMode.OwnerDrawFixed;
		}

		#region Protected Methods
		protected override void OnDrawItem(DrawItemEventArgs e)
		{
			if (e.Index>-1 && e.Index<base.Items.Count)
			{
				//Element eruieren
				object item=this.Items[e.Index];
				//EventArgs aufbereiten
				DefineHowToDrawEventArgs eSetByUser=null;
				if ((e.State & DrawItemState.Selected)==DrawItemState.Selected)
				{
					//Standard für ein selektiertes Item
					eSetByUser= new DefineHowToDrawEventArgs(item,SystemColors.Highlight,SystemColors.HighlightText,this.Font,true);
				}
				else
				{
					//Standard für ein nicht selektiertes Item
					eSetByUser= new DefineHowToDrawEventArgs(item,this.BackColor,this.ForeColor,this.Font,false);
				}

				//Event werfen
				this.OnDefineHowToDraw(eSetByUser);

				//Zeichnen
				Graphics g=e.Graphics;
			
				//Hintergrund für jedes Item
				e.DrawBackground();

				//Hintergrund füllen mit der gewünschten Farbe
				g.FillRectangle(new SolidBrush( eSetByUser.BackColor),e.Bounds);

				//Text Zeichnen
				using (Brush b=new SolidBrush(eSetByUser.ForeColor))
				{
					g.DrawString(item.ToString(),eSetByUser.Font,b,e.Bounds);
				}
				
				//Focus-Rect um das current item ziehen
				e.DrawFocusRectangle();
			}
		}
		#endregion

		#region Private Methods
		private void OnDefineHowToDraw(DefineHowToDrawEventArgs pe)
		{
			if (this.DefineHowToDraw!=null)
			{
				this.DefineHowToDraw(this,pe);
			}
		}
		#endregion

		#region Events
		public event DefineHowToDrawEventHandler DefineHowToDraw;
		#endregion

		#region Properties
		//Default auch für den Designer setzen
		[DefaultValue(DrawMode.OwnerDrawFixed)]
		public override DrawMode DrawMode
		{
			get
			{
				return base.DrawMode;
			}
			set
			{
				base.DrawMode = value;
			}
		}
		#endregion
	}

	public delegate void DefineHowToDrawEventHandler(object sender, DefineHowToDrawEventArgs e);

	public class DefineHowToDrawEventArgs : EventArgs
	{
		#region Fields
		private readonly object _Item;
		private Color _BackColor;
		private Color _ForeColor;
		private Font _Font;
		private readonly bool _Selected;
		#endregion

		#region Constructor
		public DefineHowToDrawEventArgs(object pItem, Color pBackColor, Color pForeColor, Font pFont, bool pSelected):base()
		{
			this._Item=pItem;
			this._BackColor=pBackColor;
			this._ForeColor=pForeColor;
			this._Font=pFont;
			this._Selected=pSelected;
		}
		#endregion

		#region public Properties
		public object Item
		{
			get{return this._Item;}
		}
		public Color BackColor
		{
			get{return this._BackColor;}
			set{this._BackColor=value;}
		}
		public Color ForeColor
		{
			get{return this._ForeColor;}
			set{this._ForeColor=value;}
		}

		public Font Font
		{
			get{return this._Font;}
			set{this._Font=value;}
		}
		public bool Selected
		{
			get{return this._Selected;}
		}

		#endregion
	}
}

So nun muss man nur noch den Event anschnallen und kann jedes Item so pinseln wie man will



		private void colorListBox1_DefineHowToDraw(object sender, ColorListBox.DefineHowToDrawEventArgs e)
		{
			if (e.Selected)
			{
				//In diesem Fall ändere ich nichts... ausser dem FonsStyle kursiv
				//e.BackColor=SystemColors.Highlight;
				//e.BackColor=SystemColors.HighlightText;
				e.Font=new Font(e.Font.FontFamily,e.Font.Size,System.Drawing.FontStyle.Italic);
			}
			else
			{
				//in e.Item ist das Item drin.... wenn man es castet hat man wieder das Item
				//welches man geaddet oder per DataBinding angeschnallt hat
				//in meinem Beispiel ist es ein int 
				int value=int.Parse(e.Item.ToString());

				//wenn der Wert ohne Rest durch 3 teilbar ist, dann mache 
				//bei diesem Item die Schrift Rot
				if (value%3==0)
				{
					e.ForeColor=Color.Red;
				}

				//wenn der Wert ohne Rest durch 5 teilbar ist, dann mache 
				//bei diesem Item den Hintergrund Grün
				if (value%5==0)
				{
					e.BackColor=Color.Green;
				}
			}
		}

Edit: Code angepasst damit auch selektierte Items richtig gezeichnet werden.

Gruss Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

Vielleicht möchtest du dir auch mal den Artikel ColorListBox bei CodeProject.com anschauen.

Thx, hans Code funzt TipTop.

die colorlistbox muss ich dann manuell einfügen in den code, aber wie kriege ich das hin, dass auch die events der ursprünglichen listbox wieder funktionieren?

bin leider noch ein newbe :>

i kenn mi hoid ned aus

wie binde ich die box denn in mein windows form ein?

Du findest das Control in der Toolbox. Ganz oben steht dann
"Projektname" Components.

mit freundlichen Grüßen,
Tomot

Projekte: www.gesellschaftsspieler-gesucht.de

Hallo, bin grad über diese farbige ListBox gestolpert und wollte Sie ausprobieren. Das Problem meines Vorgängers habe auch ich. Wie kommt denn die ColorListBox in die ToolBox, damit ich sie von dort auf die WindowsForm ziehen kann?

Hallo Minz,

binde die Assembly, die von der ColorListBox geliefert wird, in dein Projekt ein. Meistens checkt VS dann, dass es ein neues Control gibt, und zeigt es sofort in der Toolbox an. Wenn nicht, kannst du in der Toolbox mit einem Rechtsklick und dann "Elemente auswählen" die Assembly suchen, in der sich die ColorListBox befindet und diese einbinden.

Gruß Michbeck1983

Neulich im Computerkurs:
Mein Computer kennt Else nicht! 😁


[URL]XING-Profil[/URL]

Danke für deine Antwort. Jetzt wollte ich es grad mit Rechtsklick machen und siehe da, nun hat er die ColorListBox irgendwie doch schon in die ToolBox gepackt. Meeeerchwürdig!

Super Listbox hans!

Hab nur ein Problem: Ich kann irgendwie keine Zeile selektieren bzw. der "blaue selektiert Hintergrund" wird nicht angezeigt.

Weiß jemand eine Lösung dafür? Wäre sehr dankbar über Hilfe!

MfG
Johann

Mir scheint, das wird zunächst mal so nicht gehen. Dazu müsste nämlich DrawItemEventArgs.State ausgewertet werden, obs System.Windows.Forms.DrawItemState.Selected ist, und dann entsprechend coloriert werden.
Dazu müssten die DefineHowToDrawEventArgs also erstmal entsprechend erweitert werden.

Der frühe Apfel fängt den Wurm.

Kann es sein dass der Fehler hier liegt?

protected override void OnDrawItem(DrawItemEventArgs e)
        {
           .
.
.

                if (this.SelectedIndices.Contains(e.Index))  // Hier und
                {
                    e.DrawFocusRectangle();                  // hier
                }         .
.
.
            }
        }

Wenn ich nämlich eine Zeile anklicke und mit Breakpoint debugge wird die if-Anweisung immer mit false ausgewertet. Weiß aber nicht wieso.
hans hat auch keine idee oder?

mfg

Ich habe immer Ideen 😃

Aber das kriegt ihr auch ohne meine Hilfe zum Laufen

Gruss
Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

Code angepasst (siehe oben) damit auch selektierte Items richtig gezeichnet werden.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

Vielen herzlichen Dank!

Hi,


       MyListBoxItem item1 = new MyListBoxItem("Test1", Color.Red);
       MyListBoxItem item2 = new MyListBoxItem("Test1", Color.Green);
       MyListBoxItem item3 = new MyListBoxItem("Test1", Color.Blue);

       lb.Items.Add(item1);
       lb.Items.Add(item2);
       lb.Items.Add(item3);

        public class MyListBoxItem
        {
            public Color Color{get;set;}
            public string Data { get; set; }

            public MyListBoxItem(string data, Color color)
            {
                Color = color;
                Data = data;
            }

            public override string ToString()
            {
                return Data;
            }
        }

        void lb_DefineHowToDraw(object sender, DefineHowToDrawEventArgs e)
        {
            MyListBoxItem item = (MyListBoxItem)e.Item;
            e.ForeColor = item.Color;
        }

Kleine Erweiterung, um die Listbox zu füllen. Hier kann vorher die Farbe definiert werden. Brauchte ich für eine Status-Box, Fehler rot, normal grün usw...

Aber Danke für den Code, sehr hilfreich!

Grüße Oli

Viele Grüße, Oli