~/blog/2009/06/icons-in-einer-listview-mit-mehr-f.md

Icons in einer ListView mit mehr Farben

3 min
Collage: .NET-Logo und ListView mit farbigen Vorschaubildern

Keine Zeit? Hier die Kurzversion in 30 Sekunden.

  • Eine ImageList hat standardmäßig nur 8 Bit Farbtiefe, die Icons sehen nach 256 Farben aus.
  • Mit ColorDepth.Depth16Bit klappt es besser, Depth32Bit ist für Icons mit Alphakanal die bessere Wahl.
  • ColorDepth und ImageSize müssen vor dem Hinzufügen der Bilder gesetzt werden, sonst gehen sie verloren.
  • Die ListView in der Ansicht LargeIcon zeigt auch Bilder bis 256×256, zum Beispiel für eine Vorschau.
  • Mit zwei großen Buttons links und rechts wird daraus eine kleine Bildernavigation.

Ihr packt Bilder oder Icons in eine ListView und wundert euch, warum alles aussieht wie aus einem alten Katalog mit 256 Farben? Mir ist das auch passiert. Schuld ist nicht die ListView, sondern die ImageList dahinter.

Das Problem: 8 Bit Farbtiefe

Eine neue ImageList hat standardmäßig ColorDepth.Depth8Bit. Egal wie schön euer Bild ist, es wird auf 256 Farben gedrückt. Verläufe sehen dann körnig aus, Fotos erst recht.

Die Lösung ist simpel: Farbtiefe erhöhen. Ich hatte zuerst Depth16Bit genommen, dazu eine Bildgröße von 160 x 120. Das sieht schon deutlich besser aus. Wer aber Icons mit Alphakanal hat, also weichen Kanten und Halbtransparenz, nimmt besser Depth32Bit. Sonst bekommen die Ränder hässliche Treppen.

ImageList bilder = new ImageList();
bilder.ColorDepth = ColorDepth.Depth32Bit;
bilder.ImageSize = new Size(160, 120);

Die höhere Farbtiefe kostet etwas mehr Speicher, bei ein paar Vorschaubildern merkt man das aber nicht.

Die ListView kann übrigens viel mehr, als man erwartet. Auch große Bilder sind kein Problem, die ImageSize darf bis zu 256 x 256 Pixel gehen. Perfekt für eine kleine Bildervorschau!

Die Reihenfolge ist wichtig

Hier stolpert man gern: ColorDepth und ImageSize müsst ihr setzen, bevor ihr Bilder hinzufügt. Ändert ihr eine der beiden Eigenschaften später, verwirft die ImageList die Bilder, die schon drin sind. Dann bleibt die Liste einfach leer und man sucht sich dumm.

Außerdem gilt: Die Bilder werden beim Hinzufügen auf die ImageSize skaliert. Passt also lieber gleich das Seitenverhältnis.

Das komplette Beispiel

Hier ein vollständiges Formular mit .NET 3.5 und C# 3.0. Die Bilder bekommen einen Schlüssel, über den die Einträge der ListView sie später wiederfinden. Die Pfade müsst ihr natürlich anpassen.

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

public partial class MainForm : Form
{
    private ImageList bilder = new ImageList();
    private ListView vorschau = new ListView();
    private Button zurueck = new Button();
    private Button weiter = new Button();

    public MainForm()
    {
        InitializeComponent();

        // Erst Farbtiefe und Größe, dann die Bilder
        bilder.ColorDepth = ColorDepth.Depth32Bit;
        bilder.ImageSize = new Size(160, 120);
        bilder.Images.Add("strand", Image.FromFile(@"C:\Bilder\strand.png"));
        bilder.Images.Add("berge", Image.FromFile(@"C:\Bilder\berge.png"));

        vorschau.View = View.LargeIcon;
        vorschau.LargeImageList = bilder;
        vorschau.Dock = DockStyle.Fill;
        vorschau.BorderStyle = BorderStyle.None;
        vorschau.BackColor = this.BackColor;
        vorschau.Items.Add(new ListViewItem("Strand", "strand"));
        vorschau.Items.Add(new ListViewItem("Berge", "berge"));

        zurueck.Text = "<";
        zurueck.Dock = DockStyle.Left;
        zurueck.Width = 40;

        weiter.Text = ">";
        weiter.Dock = DockStyle.Right;
        weiter.Width = 40;

        // Das Fill-Control zuerst hinzufügen
        Controls.Add(vorschau);
        Controls.Add(zurueck);
        Controls.Add(weiter);
    }
}

Ein paar Anmerkungen dazu. Mit Images.Add(key, image) vergebt ihr den Namen, und das ListViewItem greift über den ImageKey darauf zu, ohne dass ihr Indizes zählen müsst. Mit View.LargeIcon zeigt die ListView die großen Bilder an. Die Beschriftung steht dann darunter.

Eine kleine Bildervorschau

Jetzt noch die Idee, die ich ursprünglich im Kopf hatte: Links und rechts jeweils ein großer Navigationsbutton, dazwischen die ListView. Gebt der ListView dieselbe Hintergrundfarbe wie dem Formular und nehmt den Rahmen weg, dann wirkt alles aus einem Guss. Das Ganze hat dann wirklich Hand und Fuß.

Was die Buttons tun, bleibt euch überlassen. Ich würde mit EnsureVisible an der Liste arbeiten, damit der gewünschte Eintrag in den sichtbaren Bereich scrollt.

Habt ihr eure Icons in der ListView schon mal hübscher bekommen? Oder nutzt ihr was ganz anderes für Vorschaubilder? Schreibt es mir in die Kommentare!

Beitragsbild: eigene Collage mit Logo von Wikimedia Commons (.NET-Logo (2002): Microsoft), gemeinfrei; die Marke gehört ihrem Inhaber.

$ whoami
Christian Ackermann

Softwareentwickler (C++, C, Java, C#) aus der Oberpfalz, bloggt seit 2001 über Linux, Technik und Kochen.