Das WPF DataGrid zur Darstellung tabellarischer Daten

Das WPF DataGrid als moderne Winforms DataGridView-Alternative
Das WPF DataGrid als moderne Winforms DataGridView-Alternative

Eine moderne tabellarische Darstellung mit dem WPF DataGrid

Herzlich willkommen im heutigen „WPF DataGrid„-Beitrag und schön, dass Du her gefunden hast.

Vermutlich wirst Du aus dem gleichen Problem“ wie ich damals auf diesen Post gestoßen sein.

Eventuell kennst Du das „WPF DataGrid„-Steuerelement schon, oder möchtest einfach nur Dein Wissen vertiefen.

Vielleicht möchtest Du aber auch einfach nur eine Alternative zum (sorry Winforms) hässlichen DataGridView finden.

Mal ernsthaft: Wer möchte in modernen Anwendungen noch diese an alte Windows Zeiten erinnernde Tabelle verwenden.

Eine teils hängende Performance und eine eher graue Darstellung waren an der Tagesordnung.

Wie Du später in diesem Beispiel noch sehen wirst, bietet das „WPF DataGrid“ tolle Möglichkeiten.

Neben den typischen Reihen, Spalten und sich daraus ergebenden Zellen, gibt es noch mehr zu finden.

Lass‘ uns allerdings vorerst nochmal einen kleinen Schritt zu den Windows Forms (Winforms) zurück machen.

Ich denke, so werden die Unterschiede noch einmal klarer, bzw. der Kontrast ist dadurch stärker.

Ein Rückblick auf die guten alten Winforms

Ein Rückblick zu Windows Forms - WPF DataGrid
Ein Rückblick zu Windows Forms – WPF DataGrid

Wie erwähnt gehen wir nochmal einen kleinen Schritt zurück, um zu schauen „wie es mal war„.

Zu dem Zeitpunkt war noch nicht alles sobunt„, teils „yay“, teils „nay“, oder!?

Okay, abgesehen von der Farbenpracht der Anwendungen gab es natürlich noch viele andere Aspekte.

Zum (für mich, unter Anderem) wichtigsten Aspekt kommen wir nun im nächsten Schritt.

Ein (tatsächlich) bunter Misch-Masch

Wenn ich ehrlich bin, kommen mir gewisse Dinge bei den alten Windows Forms sofort in den Sinn.

Nachträglich betrachtet empfinde ich Diese als ziemlich „komisch“, bzw. eher „unnatürlich„.

Damals hat man z. B. bei DataGridViews Sachen wie Diese hier gemacht:

DataGridView1.Rows.Add(<whatever..>)

Man hat also gängiger weise an den Steuerelementen selbst herumgedoktert.

So gesehen waren die Daten also immer ein Bestandteil des Steuerelements selbst.

Was wir jedoch – schon rein logisch gesehen – erreichen wollen, ist doch eine Darstellung der Daten, oder!?

Sprich die Daten sollen durch etwas dargestellt werden und nicht dieses „Etwas“ selbst sein.

Schauen wir uns im nächsten Schritt an, wie es (unter Anderem) sonst noch laufen kann.

Eine andere Herangehensweise – viele Schritte nach vorn

Viele (ich würde fast sagen – die meisten) NET Entwickler greifen heutzutage auf WPF zurück.

Im Gegensatz zur alten Methodik verwendet WPF eine neue Herangehensweise.

Dabei handelt es sich primär um die saubere Trennung zwischen Oberfläche und Daten.

Es sei an dieser Stelle gesagt, dass es auch bei WPF die Misch-Möglichkeit in gewisser weise gibt.

Ich selbst habe damit allerdings nie großartige Erfahrungen gemacht – auf Grund der neuen Möglichkeiten natürlich bewusst.

Durch die saubere Unterscheidung werden Templates (neben anderen Vorteilen) leichter austauschbar.

Auch wenn diese neue Herangehensweise nur einer der positiven Aspekte ist, ist es denke ich einer der Wichtigsten.

Wie wir gleich noch sehen werden, kommen mit dieser neuen Strukturierung auch weitere Werkzeuge ins Spiel.

Ich spreche da speziell von dem modernen Anwendungs-Entwurfsmuster namens „MVVM“.

Aber genug davon, zurück zur Hauptaussage: Die „bessere“ Herangehensweise bezüglich Daten- & GUI-Trennung.

Softwareentwickler und Designer können sich so trotz separierter Arbeit einander zuarbeiten.

Natürlich basiert dies alles auf einem sauberen vorher abgeklärten Konsens!

3x-mini MVVM-Exkurs

Das „Model-View-ViewModel„-Entwurfsmuster würde mit Sicherheit mehr Aufmerksamkeit verdienen, aber gut..

Ich versuche natürlich, es hier nicht all zu weit auszuführen, daher hier ein paar kurze Argumente/Aspekte.

Das MVVM-Entwurfsmuster spielt in den meisten „Windows Presentation Foundation“ (WPF) Apps eine große Rolle.

Nicht zuletzt deshalb, weil dieses Entwurfsmuster folgende Eigenschaften mit sich bringt:

  • Trennung von GUI & Daten
  • Moderne Anwendungen
  • Intuitive Oberflächen
  • Flexible Programmierung
  • eine ausgereifte Designer-Unterstützung
  • und viel mehr..

Schaue für mehr Informationen gerne im obigen Beitrag vorbei, wundere Dich allerdings nicht.

Bisher habe ich noch keinen separaten Beitrag für MVVM in Visual Basic NET geschrieben.

Das macht allerdings insofern nichts, da die Umsetzung nicht wirklich an der Sprache liegt.

Doch zurück zum Thema: Was machen die restlichen, noch verbliebenen Softwareentwickler?

Die meisten werden wohl die für Windows Forms typischen Steuerelemente verwenden.

Ausnahmen (sorry Leute) verwenden wohl irgendwelche gekauften Steuerelemente und dazugehörige Bibliotheken.

Ich selbst habe zum Beispiel noch nie Geld für Steuerelemente oder ähnliches ausgegeben.

Es gibt meiner Ansicht nach einfach zu viele wirklich gute kostenlose Werkzeuge.

Einige davon wären:

  • Autofac
  • Caliburn.Micro
  • Mahapps Metro

Zu einigen dieser Werkzeuge habe ich schon Beiträge erstellt, Andere folgen in Zukunft!

Das WPF DataGrid selbst

Das WPF DataGrid selbst - Daten Beispiel
Das WPF DataGrid selbst – Daten Beispiel

Nach dem ganzen leider für die Suchmaschinenoptimierung notwendigen Blabla„, nun zum eigentlichen Thema.

Zuerst setzen wir dafür natürlich ein neues Visual Studio Projekt namens „WPF-Anwendung“ auf.

Wenn Du nach einem Thema wie das WPF DataGrid suchst, wird Dir vermutlich bekannt sein wie das geht.

Neues Projekt anlegen

Falls nicht öffnest Du einfach Visual Studio und klickst dort unten rechts auf „neues Projekt erstellen„.

Danach musst Du das passende Projekt-Template auswählen, suche dazu oben rechts einfach nach „wpf“.

Anschließend solltest Du einen Eintrag a la „WPF-Anwendungfinden.

Achte jedoch darauf, die korrekte Sprache (VB.NET / C#) zu wählen, damit es gleich keine Verwirrung gibt.

Danach bestimmst Du noch den passenden Namen für Projekt und Projektname.

Zum Schluss wählst Du noch das passende NET-Framework aus und – neues Projekt – check!

Ich kann Dir übrigens eine eventuelle Sorge bezüglich der Programmiersprache nehmen.

Die Sprache macht hier für unsere Beispiel keinen wirklich großen oder relevanten Unterschied.

Eine Klasse anlegen – der Bauplan für unsere Daten

Im nächsten Schritt erstellen wir eine kleine Klasse, die dann unsere Daten widerspiegelt.

Zu diesem Zeitpunkt besteht unsere neu erstellte Anwendung praktisch nur aus einem Fenster.

Dabei handelt es sich um die typische WPF-Fenster Klasse, Welche man in so gut wie jedem Programm antrifft.

Lass‘ uns nun einmal unsere Gedanken vom Steuerelement-Kram an sich beiseite schieben.

Werfen wir daher einen Blick auf die „Daten“, bzw. den Bauplan dafür an sich.

Wie sollen wir schließlich auch „etwas“ erstellen, bzw. in einem WPF DataGrid auflisten, wenn es dieses „etwas“ noch nicht gibt.

Erstelle also eine neue Klasse namens „Film“, Diese kannst Du auch ruhig im Wurzelverzeichnis ablegen.

Bedenke, dass ich die Klasse hier erstmal relativ einfach halten werde, also „flach“ und mit wenig Eigenschaften.

Daher werde ich die „Genre„-Eigenschaft z. B. nicht als getrennte Klasse designen, sondern eher als simplen String.

Public Class Film
  
  Public Property Titel As String

  Public Property Genre As String

  Public Property Bewertung As Decimal

End Class
public class Film
{
  
  public string Titel { get; set; }

  public string Genre{ get; set; }

  public decimal Titel { get; set; }

}

Daten kreieren – die Film-Instanzen, der Datenkontext und die Auflistung

Nachdem wir nun unseren Bauplan, also die „Film“-Klasse vorbereitet haben, wagen wir uns an die Datenbindung.

Gehe zuerst in die „MainWindow.xaml“-Datei und füge das WPF DataGrid in den standardmäßig leeren Fenster-Code ein.

Die genaue Position für den DataGrid-Code wäre natürlich zwischen den „Grid„-Tags.

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfDataGridExampleVB"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid />
    </Grid>
</Window>

Von nun an kommt es darauf an, wie Du vor hast Deine Daten erscheinen zu lassen.

Öffne nun die Code-Datei hinter dem WPF-Fenster, damit wir am Code arbeiten können.

Dazu kannst Du entweder bei geöffnetem Designer F7“ drücken, oder über den Projektmappen-Explorer gehen.

Klappe dazu den Pfeil des „MainWindows“ im Projektmappen-Explorer auf und doppelklicke die „MainWindow.xaml.vb“-Datei.

Die normale non-MVVM Variante

Um die gleich folgenden Daten anzuzeigen, nehmen wir zuerst die (vermeintlich) einfachste Variante.

Nutze nun einen der verschiedenen Wege, um einen Loaded„-Ereignishandler für das Fenster zu generieren.

Gehe in der Code-Datei z. B. hin und wähle in der mittleren Combobox im obigen Fenster-Bereich „(MainWindow Ereignisse)“.

Dann kannst Du in der nächsten Combobox rechts daneben das passende Ereignis auswählen und Dir den Handler generieren lassen.

Einen WPF DataGrid Loaded-Ereignishandler generieren
Einen WPF DataGrid Loaded-Ereignishandler generieren

Nun sieht der generierte „Loaded„-Ereignishandler wie gleich folgend aus und wir können Code ergänzen.

Zuerst musst Du noch daran denken (zumindest in diesem Beispiel), dem DataGrid einen Namen zu geben.

Da wir in diesem Beispiel die Code-Behind/Non-MVVM Variante verwenden, füge den Namen im XAML-Tag hinzu:

<DataGrid Name="FilmsDataGrid" />

Damit haben wir die Möglichkeit, das WPF DataGrid in der Code-Datei anzusprechen und dessen Eigenschaften zu setzen.

Ich betone nochmal, dass dies in der Welt von WPF eigentlich nicht der bevorzugte Weg ist.

Immerhin ist diese Variante trotzdem besser, als das oben vom DataGridView bekannte „DataGridView.Rows.Add“.

Im Endeffekt möchte ich diesen Weg natürlich zeigen, um auch dieses Beispiel bereitzustellen.

Datenquelle erstellen und setzen

Damit wir dem DataGrid nun sagen können, dass es Daten anzeigen soll, sprechen wir es an.

Die Eigenschaft, Welche für uns von Interesse ist, ist die „ItemsSource„-Eigenschaft.

Bevor wir die Item-Quelle nun setzen können, müssen wir erstmal eine Art Quelle erstellen.

Verwende hierzu eine Instanz der generischen „ObservableCollection„-Klasse.

Um zu vermeiden, dass der Beitrag nachher 4000 Wörter beinhaltet, nur so viel zur Klasse, Sie ist:

  • generisch – kann also mit verschiedenen Typen wie unsere Filme verwendet werden
  • mitteilend – Sie kann über Änderungen (neue, oder gelöschte Einträge, etc.) Bescheid geben
  • einfach – durch die für Listen übliche Funktionen ist Sie einfach zu bedienen

Der komplette Code zum Fenster sieht nun so aus:

Imports System.Collections.ObjectModel

Class MainWindow

    Public Property Filme As ObservableCollection(Of Film)

    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Filme = New ObservableCollection(Of Film)()
        Filme.Add(New Film() With {.Titel = "Last Samurai", .Genre = "Krieg/Action", .Bewertung = 5})
        Filme.Add(New Film() With {.Titel = "The Green Mile", .Genre = "Fantasy/Drama", .Bewertung = 5})
        Filme.Add(New Film() With {.Titel = "Die Verurteilten", .Genre = "Drama/Krimi", .Bewertung = 5})
        FilmsDataGrid.ItemsSource = Filme
    End Sub

End Class
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

class MainWindow
{
    public ObservableCollection<Film> Filme { get; set; }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        Filme = new ObservableCollection<Film>();
        Filme.Add(new Film() { Titel = "Last Samurai", Genre = "Krieg/Action", Bewertung = 5 });
        Filme.Add(new Film() { Titel = "The Green Mile", Genre = "Fantasy/Drama", Bewertung = 5 });
        Filme.Add(new Film() { Titel = "Die Verurteilten", Genre = "Drama/Krimi", Bewertung = 5 });
        FilmsDataGrid.ItemsSource = Filme;
    }
}

Zuerst instanziieren wir die Filme-Auflistung und fügen Ihr anschließend verschiedene Einträge hinzu.

Danach setzen wir die „ItemsSource“-Eigenschaft, um die Auflistung zu „binden„.

Hier siehst Du das aktuelle Ergebnis:

DataGrid ItemsSource Eigenschaft durch Code-Behind setzen
DataGrid ItemsSource Eigenschaft durch Code-Behind setzen

Die DataContext-ViewModel-Variante

Machen wir im nächsten Schritt ein Beispiel zur MVVM orientierten Variante, also mit einem Datenkontext.

Dazu müssen wir zuerst eine Klasse, also einen Bauplan anlegen, Welcher dann als Datenkontext dient.

Danach müssen wir der „DataContext„-Eigenschaft des WPF-Fensters einen Wert zuweisen.

Richtigerweise verwenden wir hier natürlich eine Instanz der folgenden Klasse:

Imports System.Collections.ObjectModel

Public Class MeinMainWindowDatenkontext

    Public Property Filme As ObservableCollection(Of Film)

    Sub New()
        Filme = New ObservableCollection(Of Film)
    End Sub

    Public Sub LadeTestFilme()
        Filme.Add(New Film() With {.Titel = "Last Samurai", .Genre = "Krieg/Action", .Bewertung = 5})
        Filme.Add(New Film() With {.Titel = "The Green Mile", .Genre = "Fantasy/Drama", .Bewertung = 5})
        Filme.Add(New Film() With {.Titel = "Die Verurteilten", .Genre = "Drama/Krimi", .Bewertung = 5})
    End Sub

End Class
using System;
using System.Collections.ObjectModel;

public class MeinMainWindowDatenkontext
{
    public ObservableCollection<Film> Filme { get; set; }

    public MeinMainWindowDatenkontext()
    {
        Filme = new ObservableCollection<Film>();
    }

    public void LadeTestFilme()
    {
        Filme.Add(new Film() { Titel = "Last Samurai", Genre = "Krieg/Action", Bewertung = 5 });
        Filme.Add(new Film() { Titel = "The Green Mile", Genre = "Fantasy/Drama", Bewertung = 5 });
        Filme.Add(new Film() { Titel = "Die Verurteilten", Genre = "Drama/Krimi", Bewertung = 5 });
    }
}

Den Code der Form würden wir dann so anpassen:

Class MainWindow

    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Dim datenKontext = New MeinMainWindowDatenkontext()
        datenKontext.LadeTestFilme()
        DataContext = datenKontext
    End Sub

End Class
class MainWindow
{

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        var datenKontext = new MeinMainWindowDatenkontext();
        datenKontext.LadeTestFilme();
        DataContext = datenKontext;
    }

}

Den XAML-Code müssen wir letztendlich auch noch anpassen.

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfDataGridExampleVB"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid ItemsSource="{Binding Filme}" />
    </Grid>
</Window>

Damit sagen wir dem Fenster, bzw. genauer genommen dem DataGrid: „Hey, deine Items findest Du in der Datenkontext-Eigenschaft namens Filme

Fazit

Das WPF DataGrid als moderne Tabelle - Ein Fazit

Am Ende unseres heutigen Beitrages angekommen, lassen wir die wichtigsten Aspekte nochmal aufleuchten.

Zusammengefasst ist das WPF DataGrid ein modernes Steuerelemente, Welches die Darstellung von tabellarischen Daten unterstützt.

Das Steuerelement kann auf viele Arten und Weisen den eigenen Bedürfnissen angepasst werden.

Im heutigen Beitrag habe ich Dir gezeigt, wie Du Daten auf View-Basis anzeigst.

Danach haben wir uns die etwas modernere Variante mit Hilfe eines ViewModels angeschaut.

Moderne Anwendungen verwenden besonders in Kombination mit WPF eigentlich nur noch das MVVM-Entwurfsmuster.

Geplante Erweiterungen

Für diesen Beitrag habe ich in Zukunft noch folgende eventuelle Beispiele geplant:

  • Mehr Fokus auf Styling
  • Arbeit mit Datensätzen
  • Ähnliches..

Downloads für WPF DataGrid

Weiterführende Links

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.