[C#] Alternierende Itemfarbe in ListBox

Drucken
( 0 Votes ) 
Hauptkategorie: Programmieren Kategorie: C#
Erstellt am 08.12.2011 Zuletzt aktualisiert am 02.02.2012 Geschrieben von Jonny132
Ich habe mir die Aufgabe gestellt in einem Listview zur besseren Anzeige eine Alternierende Farbe einzbauen. Das heisst, dass jede Zeile abwechselnd eingefärbt wird. Dies stellte sich als schwieriger heraus als es scheint, doch es ist möglich mit ein bisschen trickserei.

Zunächst Erstellen wir ein neues Forms Projekt und fügen dieser ein neues UserControl hinzu das wir von der ListBox ableiten. Dieses UserControl gebe ich den Namen ExtendedListBox.

ExtendedListBox Gerüst

namespace WindowsFormsApplication1
{
   public partial class ExtendedListBox : ListBox
   {
   }
}

Als neue Eigenschaft geben wir der ExtendedListBox ein Color Objekt. Wir geben ihr den Namen AlternatingColor.
Gleichzeitig setzen wir im Konstruktor die Eigenschaft DrawMode auf OwnerDrawFixed. Diese Änderung bezweckt, dass wir die Items selbst zeichnen können in dem wir das OnDrawItem - Event überschreiben.

Property und Konstruktor der ExtendedListBox

 public Color AlternatingColor { get; set; } 
 public ExtendedListBox()
 {
    InitializeComponent();
    this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
 }

Wie eben erwähnt können wir nun dank OwnerDrawFixed das OnDrawItem Event überschreiben. Würden wir diesen Status nicht setzen, würde das Event nie aufgerufen werden.

OnDrawItem Event der ExtendedListBox

protected override void OnDrawItem(DrawItemEventArgs e)
 {
   if (this.Items.Count > 0)
   {
     if (AlternatingColor != null && e.Index % 2 == 1 &&
          e.State != DrawItemState.Selected && 
          e.State != (DrawItemState.Selected | DrawItemState.Focus))
     {
       e.Graphics.FillRectangle(new SolidBrush(AlternatingColor), e.Bounds);
     }
     else
     {
       e.Graphics.FillRectangle(new SolidBrush(e.BackColor), e.Bounds);
     }
     e.Graphics.DrawString(this.Items[e.Index].ToString() e.Font,
                           new SolidBrush(e.ForeColor), e.Bounds);
   }
 }
Zuerst wird ausgeschlossen, dass unsere ExtendedListBox keine Elemente hat, da es sonst zu einem Fehler im Designer und zur Laufzeit kommen könnte und unsere Eigenschaft Alternating Color keinen Wert hat. Dann überprüfen wir ob der aktuell gezeichnete ListBox Eintrag eine alternierende ist indem wir den Index darauf prüfen, ob er bei einer Division durch 2 einen Rest von 1 hat. Dafür benützen wir den Modulo Operator. Zuletzt überprüfen wir noch ob der aktuelle Status des zu zeichnenden ListBoxItems nicht Selectiert ist und nicht Selectiert+Fokussiert. Der Status Selectiert+Fokussiert bekommt ein Item in dem Sie per gedrückter Maustaste über die ListBox ziehen würden. Deswegen müssen wir diesen Status auch ausschlissen.

Treffen all diese Bedinungen zu, zeichen wir den Hintergrund mit der unserer Alternierenden Farbe.

Wenn die zeile nicht alternierend ist und / oder selektiert, wird der Standardhintergrund gemalt.

Zu Schluss des Events wird noch der Text des aktuellen Items gezeichnet.

Nun sind alle voraussetzungen getroffen und unser ExtendedListBox - Control fertig.

Kompilieren Sie nun das Projekt und Sie haben in der Toolbox die neue ExtendedListBox zur Auswahl. Ziehen Sie diese nun auf die Form und wechseln Sie in die Codeansicht.

Form Load Ereignis

private void Form1_Load(object sender, EventArgs e)
 {
   extendedListBox1.AlternatingColor = Color.Yellow;
   for (int i = 0; i < 200; i++)
   {
     extendedListBox1.Items.Add("ListBox Item " + i.ToString());
   }
 }

Im Load Ereignis der Form weisen wir nur noch der ExtendedListBox eine Alternierende Farbe zu und fügen per Schleife ein paar Einträge hinzu.

Starten Sie das Projekt und Sie sehen das Ergebnis:

Alternierende ListBox

  • FruitNoob

    schrieb am 2014-01-03 14:57:01

    Vielen Dank für diese anschauliche Anleitung.

    Bei mir gab es nur einen Fehler:
    Die neue Klasse kennt die Funktion InitializeComponent() im Konstruktor nicht. Ich habe die Zeile dann einfach auskommentiert, danach hat es perfekt funktioniert.

    Danke

    Auf Kommentar antworten

    • Jonny132

      schrieb am 2014-01-07 17:24:06

      Hallo FruitNoob,

      wenn du es so machst wie beschrieben - also ein neues UserControl anlegst, dann gibt es auch eine InitializeComponent()-Funktion.

      Jedoch wenn du stattdessen nur eine Klasse anlegst und ableitest brauchst du das nicht ;)

      Trotzdem danke.

      Auf Kommentar antworten

Veröffentlichen Sie ihre Kommentare ...