[Windows Forms] Listbox Fontcolor ZEILENWEISE einstellen?
-
Freitag, 17. August 2012 08:58
Hallo Freunde,
SZENARIO:
zum Absetzen von Meldungen nutze ich eine Listbox. Je nach Art der Meldung soll der hinzugefügte Text eine bestimmte Farbe haben.
PROBLEM:
Wenn man die Color-Property der Listbox ändert, dann ändert das ALLE Zeilen.
FRAGE:
Wie geht es aber zeilenweise??
MfG
Flux1989
Alle Antworten
-
Freitag, 17. August 2012 11:50Beantworter
Hallo,
dazu müsstest Du Owndraw ListBox verwenden
und die Elemente im DrawItem-Ereignis zeichnen.Gruß Elmar
-
Freitag, 17. August 2012 13:24
Hi Elmar,
meinst du OnDraw() oder OwnDraw()? Lösen diese das DrawItem-Ereignis aus? Wenn ja, wann/durch wen wird On/OwnDraw() aufgerufen? In der DrawItem-Beschreibung (in den listbox1-Eigenschaften) steht "Occurs whenever a particular item/area needs to be painted." Was mir aber immernoch nicht erklärt, wann das Event ausgelöst wird...
Ich kann zwar den DrawItemEventHandler generieren lassen und mit e.Graphics.DrawString(...myBrush...) die Farbe bestimmen, kapiere aber nicht wer wann warum DrawItem-Event auslöst?
ganz schön kompliziert für so eine simple Aufgabe :(
-
Freitag, 17. August 2012 13:34
Zu meinem Aufbau: ich habe zwei Klassen: eine für die BusinessLogik (B) und eine für die Form (F). In B rufe ich mein eigenes Event msg("ich soll auf die listbox", "green") auf, welches in F behandelt wird durch msg2Listbox().
In msg2Listbox() müsste ich nun On/OwnDraw() aufrufen mit new DrawItemsEventArgs(...foreClolor...), abhängig davon welche Farbe in msg mitgeliefert wurde.
Oder liege ich komplett falsch?
-
Freitag, 17. August 2012 13:49Beantworter
Hallo,
gemalt wird immer dann, wenn das Element angezeigt wird.
Was zum einen durch das Rollen in der Auflistung passiert,
zum anderen aber auch, wenn das Element neu aufgebaut wird -
z. B. wenn es zwischenzeitlich von einem anderen Fenster verdeckt wurde.Deswegen wirst Du da kaum Ereignisse "zwischen schieben" können.
Deine Elemente müssen zu jeder Zeit ermitteln können, welche Farbe sie gerade haben. Und sollte sich der Status (Farbe) ändern musst Du die Auflistung neuzeichnen - ein Invalidate für die Listbox wäre der einfachste Weg.Ein Beispiel hatte ich vor kurzem mal gegeben in: Listboxen flackern
wobei Du beim DrawText jeweils Deine Farbe einsetzen müsstest -
die MSDN Dokumentation zeigt das auch andeutungsweise.Gruß Elmar
-
Freitag, 17. August 2012 14:03
gemalt wird immer dann, wenn das Element angezeigt wird. Was zum einen durch das Rollen in der Auflistung passiert, zum anderen aber auch, wenn das Element neu aufgebaut wird - z. B. wenn es zwischenzeitlich von einem anderen Fenster verdeckt wurde.
Wird DrawItem auch aufgerufen, wenn ich listbox1.Items.Add("ich bin eine bunte Zeile") aufrufe?
Deswegen wirst Du da kaum Ereignisse "zwischen schieben" können.
Es ist also nicht möglich OnDrawItem bzw. DrawItem "händisch" in meinem eigenen EventHandler mit eigenen DrawItemEventArgs aufzurufen?
Deine Elemente müssen zu jeder Zeit ermitteln können, welche Farbe sie gerade haben.
Und sollte sich der Status (Farbe) ändern musst Du die Auflistung neuzeichnen -
ein Invalidate für die Listbox wäre der einfachste Weg.
Du sprichst in Rätseln.. ??
Ein Beispiel hatte ich vor kurzem mal gegeben in: Listboxen flackern
Gut, das ist ja einfach die Behandlung des DrawItem-Events wie hier beschrieben
Ich versteh noch nicht wann OnDrawItem aufgerufen wird bzw. ob ich das DrawItem-Event selber auslösen kann und dabei die Farbe übergeben
-
Freitag, 17. August 2012 14:45Warum kann Microsoft nicht einfach listbox1.Items.Add(string text, string color) bereitstellen :@
-
Freitag, 17. August 2012 14:57
Im Moment sieht mein Code so aus:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace WindowsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } string text = "ich werde angezeigt"; string color = "green"; private void button1_Click(object sender, EventArgs e) { listBox1.Items.Add("ich loese DrawItem-Event aus, werde aber nicht angezeigt"); listBox1_DrawItem(this, new DrawItemEventArgs(), text, color); } //listbox1.DrawMode = OwnerDrawVariable; //Eigene Behandlung des DrawItem-Event private void listBox1_DrawItem(object sender, DrawItemEventArgs e, string txt, string clr) { e.DrawBackground(); Brush brush = Brushes.Red; e.Graphics.DrawString(txt, e.Font, brush, e.Bounds, StringFormat.GenericDefault); e.DrawFocusRectangle(); } } }Über txt und clr möchte ich im DrawItem-EventHandler bzw. e.Graphics.DrawString(..txt...clr..) manipulieren, was leider nicht funktioniert.
Irgendwie brauche ich innerhalb listbox1_DrawItem() eine Bedingung, anhand derer ich die jeweilige Zeilenfarbe bestimmen kann ("case x: Brush mybrush = Brushes.x")
Hilfe :(
- Bearbeitet Flux1989 Freitag, 17. August 2012 15:01
-
Freitag, 17. August 2012 16:27Beantworter
Hallo,
das Ereignis wird von der ListBox angestossen, über einen Button geht das nicht. So registriert mein Beispiel (im Konstruktor):
// Für OwnerDraw (ohne zappelt es ;-() this.lbDgvDates.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; this.lbDgvDates.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.lbDgvDates_DrawItem);
Wenn Du in Deiner Klasse eine Eigenschaft hinterlegst, anhand der Du die Farbe ermitteln kannst, so kannst Du über den Index darauf zugreifen.
Gruß Elmar
-
Freitag, 17. August 2012 16:50
Wenn Du in Deiner Klasse eine Eigenschaft hinterlegst, anhand der Du die Farbe ermitteln kannst, so kannst Du über den Index darauf zugreifen.
wie soll das gehen? e.index ist doch die Zeilennummer von listbox1.Items, oder? In Items stehen die Textzeilen der Listbox, was wiederum bedeuten würde, dass ich die jew. Zeilenfarbe in den Text einer Zeile kodieren müsste, bspw. über Schlüsselworte wie "Fehler: ich bin eine Fehlermeldung" und dann über das vorangestellte "Fehler:" Brushes.Red setzen?
-
Freitag, 17. August 2012 18:33Beantworter
Hallo,
ein bissel weiter als bis zu einem String wirst Du schon müssen.
Ein noch minimaleres Beispiel:using System.Drawing; using System.Windows.Forms; namespace ElmarBoye.Samples.Forms { public partial class ListBoxOwnerDrawSimpleForm : Form { public ListBoxOwnerDrawSimpleForm() { // enthält eine ListBox namens listBox1 InitializeComponent(); this.listBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; this.listBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.listBox1_DrawItem); this.listBox1.Items.AddRange(new ColoredItem[] { new ColoredItem() { Name = "1. Zeile", Color = Color.Black}, new ColoredItem() { Name = "2. Zeile", Color = Color.Red}, new ColoredItem() { Name = "3. Zeile", Color = Color.Green}, new ColoredItem() { Name = "4. Zeile", Color = Color.Blue} }); } /// <summary>Minimalistische OwnerDraw Variante.</summary> private void listBox1_DrawItem(object sender, DrawItemEventArgs e) { ListBox listBox = (ListBox)sender; var drawItem = (ColoredItem)listBox.Items[e.Index]; string drawText = drawItem.Name ?? "<Leer>"; Color foreColor = drawItem.Color; e.DrawBackground(); e.DrawFocusRectangle(); TextRenderer.DrawText(e.Graphics, drawText, e.Font, e.Bounds, foreColor, e.BackColor, TextFormatFlags.Default); } } public class ColoredItem { public string Name { get; set; } public Color Color { get; set; } } }
Gruß Elmar- Als Antwort markiert Flux1989 Samstag, 18. August 2012 19:41
-
Samstag, 18. August 2012 05:16Moderator
Hallo Flux1989 und Elmar,
Als Alternative könnte man statt der ListBox das ListView-Steuerelement einsetzen. Jedes ListViewItem-Element hat eine ForeColor- und eine BackColor-Eigenschaft:
// Optional: ListView als ListBox "tarnen" listView1.View = View.Details; listView1.HeaderStyle = ColumnHeaderStyle.None; listView1.FullRowSelect = true; listView1.Columns.Add("Farben"); listView1.Columns[0].Width = listView1.Width -22; // Farben setzen var item1 = listView1.Items.Add("Rot"); item1.ForeColor = Color.Red; item1.BackColor = Color.White; ListViewItem item2 = new ListViewItem(new[] { "Blau" }, -1, Color.Blue, listView1.BackColor, Font); listView1.Items.Add(item2);
GrußMarcel
- Als Antwort vorgeschlagen Elmar BoyeMVP, Editor Samstag, 18. August 2012 17:43
- Als Antwort markiert Flux1989 Samstag, 18. August 2012 19:41
-
Samstag, 18. August 2012 17:32
Hallo Elmar & Marcel,
da ListViewItems standardmaessig mit einer ForeColor-Eigenschaft daherkommen (und daher ohne zusaetzliche ColoredItem-Klasse auskommen) und generell einfacher zu handlen sind, favorisiere ich die Listview-Variante gegenueber der ListBox, und habe nun die ListView entsprechend implementiert!
Vielen Dank an euch!
Flux89

