EDM: Kunden verwalten mit Ribbon

Bisher haben wir in diesem Magazin nur einzelne Beispiele zur Darstellung von Daten aus Tabellen geliefert. Diesmal wollen wir einen Schritt weiter gehen: Wir erstellen eine WPF-Anwendung, die ein eigenes Ribbon enthält und mit diesem die Steuerung einiger Funktionen zur Auflistung von Kunden sowie zum Bearbeiten, Hinzufügen und Löschen von Kundendatensätzen ermöglicht. Dabei nutzen wir als Container für die angezeigten Seiten mit der Kundenliste und den Kundendetails ein Frame-Objekt. Damit können wir, wenn mehrere Benutzer geöffnet sind, sogar durch die entsprechenden Seiten navigieren.

Dabei wollen wir zunächst eine Kundenübersicht und später eine Seite zum Anlegen eines neuen Kunden über entsprechende Ribbon-Steuerelemente sichtbar machen. Eine weitere Schaltfläche soll den aktuell in der Kundenübersicht markierten Kunden löschen.

Das heißt, dass wir zunächst ein Ribbon im Fenster MainWindow unserer Beispielanwendung benötigen, das drei Schaltflächen für die gewünschte Navigation in den Kundendatensätzen und eine Schaltfläche zum Schließen des Fensters enthält. Dies sollte später so wie in Bild 1 aussehen.

Erster Entwurf des Ribbons

Bild 1: Erster Entwurf des Ribbons

Um dies zu realisieren, legen Sie zunächst ein neues Projekt des Typs Visual C#|WPF-Anwendung namens NavigationMitRibbons an. Um die Ribbons zu definieren, benötigen Sie einen neuen Verweis, den Sie über den Verweis-Manager (Menü-Eintrag Projekt|Verweise) hinzufügen. Der Verweis heißt System.Windows.Controls.Ribbons.

Da wir dem Window-Element im Kopf ein Ribbon und darunter die Steuerelemente zur Anzeige der Artikel- und der Kundenübersicht hinzufügen wollen, legen wir zunächst ein Grid mit zwei Zeilen an. Diese definieren wir wie folgt:

<Grid.RowDefinitions>
     <RowDefinition Height="Auto"></RowDefinition>
     <RowDefinition></RowDefinition>
</Grid.RowDefinitions>

Anschließend fügen wir dem Grid ein Ribbon-Element mit zwei Schaltflächen in verschiedenen Gruppen hinzu, das wir über das Attribut Grid.Row=”0″ der ersten Ribbonzeile zuweisen (siehe Listing 1). Diesem fügen wir ein RibbonTab-Element mit zwei RibbonGroup-Elementen hinzu. Die erste Gruppe statten wir mit drei RibbonButton-Elementen aus und die zweite mit einem RibbonButton-Element. Die Schaltflächen versehen wir mit Attributen, die auf die jeweiligen Ereignismethoden verweisen. Außerdem legen wir mit der Eigenschaft LargeImageSource den Namen jeweils einer Bilddatei fest, die im Ribbon für die jeweilige Schaltfläche angezeigt werden soll. Diese Bilder legen wir in einem Unterordner namens images im Projektmappen-Explorer ab.

<Ribbon Name="rbnMain" Title="Beispielribbon" Grid.Row="0">
     <RibbonTab Name="Tab1" Header="Stammdaten" KeyTip="A">
         <RibbonGroup Header="Kunden">
             <RibbonButton Name="btnKundenuebersicht" Label="Kundenübersicht" Click="btnKundenuebersicht_Click" 
                 LargeImageSource="images\users.png"></RibbonButton>
             <RibbonButton Name="btnNeuerKunde" Label="Neuer Kunde" Click="btnNeuerKunde_Click" 
                 LargeImageSource="images\user_add.png"></RibbonButton>
             <RibbonButton Name="btnKundeLoeschen" Label="Kunde löschen" Click="btnKundeLoeschen_Click" 
                 LargeImageSource="images\user_delete.png" IsEnabled="false"></RibbonButton>
         </RibbonGroup>
         <RibbonGroup Header="Allgemein">
             <RibbonButton Name="btnSchliessen" Label="Schließen" Click="btnSchliessen_Click" 
                 LargeImageSource="images\close.png"></RibbonButton>
         </RibbonGroup>
     </RibbonTab>
</Ribbon>

Listing 1: Code für ein Ribbon mit Schaltflächen in verschiedenen Gruppen

Seiten erstellen

Nun wollen wir die beiden Seiten erstellen, die durch einen Mausklick auf die beiden Ribbon-Einträge angezeigt werden sollen. Dazu legen Sie zunächst ein erstes neues Page-Element an und nennen es Kundenuebersicht (Strg + Umschalt + A, dann Seite (WPF) auswählen und den Namen unten angeben) – siehe Bild 2.

Hinzufügen eines Page-Elements

Bild 2: Hinzufügen eines Page-Elements

Das Ergebnis ist ein transparentes, rechteckiges Objekt, für das weder Höhe noch Breite mit den üblichen Attributen Height oder Width festgelegt sind. Stattdessen finden wir die beiden Attribute d:DesignHeight und d:DesignWidth. Aber was sind das für Eigenschaften Eigenschaften, die mit d: beginnen, sind Eigenschaften für die Design-Ansicht, die nur die Größe des Page-Elements für die Entwurfsansicht markieren.

Zur Laufzeit wird das Page-Element ja ohnehin in das Frame-Element eingebettet und nimmt dessen Größe an. Dementsprechend finden Sie im Page-Element die beiden Eigenschaften d:DesignHeight und d:DesignWidth. Das Attribut mc:Ignorable=”d” gibt dem Interpreter zu verstehen, dass Attribute mit führendem d nicht interpretiert werden sollen:

<Page x:Class="NavigationMitRibbons.Kundenuebersicht" 
     ...
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"
     Title="Kundenuebersicht">

Datenquelle

Als Datenquelle für dieses Beispiel verwenden wir wieder die Datenbank Bestellverwaltung, die Sie bereits in weiteren Artikeln in diesem Magazin kennen gelernt haben. Dazu haben wir wieder ein Entity Data Model namens BestellverwaltungEntities angelegt.

Page mit Kunden füllen

Damit das Page-Element die Kunden in einer entsprechenden Liste, hier in Form eines DataGrid-Elements, anzeigt, stellen wir zunächst eine entsprechende Datenquelle in Form eines List-Objekts in der Code behind-Datei Kundenuebersicht.xaml.cs zur Verfügung, die wir innerhalb der Konstruktor-Methode der Klasse füllen (siehe Listing 2).

public partial class Kundenuebersicht : Page {
     BestellverwaltungEntities dbContext;
     private List<Kunde> kunden;
     public List<Kunde> Kunden {
         get {
             return kunden;
         }
         set {
             kunden = value;
         }
     }
     public Kundenuebersicht(int kundeID = 0) {
         InitializeComponent();
         dbContext = new BestellverwaltungEntities();
         kunden = new List<Kunde>(dbContext.Kunden);
         DataContext = this;
         if (kundeID != 0) {
             Kunde currentKunde = dbContext.Kunden.Find(kundeID);
             dgKunden.SelectedItem = currentKunde;
             dgKunden.ScrollIntoView(currentKunde);
         }
     }
}

Listing 2: Code behind-Datei der Page-Klasse Kundenuebersicht.xaml

In der Konstruktor-Methode der Klasse Kundenuebersicht wird zunächst die Methode InitializeComponent ausgeführt, um das Fenster entsprechend der XAML-Definition aufzubauen. Danach erstellen wir das Entity Data Model-Objekt dbContext auf Basis der Klasse BestellverwaltungEntities. Die Liste kunden, die wir zuvor als privates List-Objekt deklariert haben, füllen wir dann mit der Auflistung Kunden des dbContext-Objekts:

kunden = new List<Kunde>(dbContext.Kunden);

Danach weisen wir dem Page-Objekt mit der DataContext-Eigenschaft als Datenherkunft die Code behind-Klasse selbst zu. Damit die Seite nun auf die Kunden-Liste aus der Variablen kunde zugreifen kann, stellen wir diese noch mit einer öffentlichen Variablen namens Kunden zur Verfügung:

public List<Kunde> Kunden {
     ...
}

Desweiteren haben Sie sicher bemerkt, dass wir einen optionalen Parameter namens kundeID für die Konstruktormethode angelegt haben. Diese wird in der if-Bedingung interessant: Ist kundeID nämlich nicht 0, was geschieht, wann immer eine Kunden-ID übermittelt wird, dann liest die Methode den Kunden mit dieser ID in die Variable currentKunde ein. Dieser wird dann im DataGrid als aktueller Kunde markiert. Die Methode ScrollIntoView sorgt dann noch dafür, dass dieser Datensatz auch noch in den sichtbaren Bereich verschoben wird. Letzteres ist für Access/VBA-Programmierer natürlich ein Traum – dort waren für eine solche Aktion durchaus größere Verrenkungen nötig.

DataGrid-Element in Page anlegen

Schließlich wollen wir ein DataGrid-Element im Page-Element anlegen, das wie in Listing 3 definiert wird. Die Seite hat ja als Datenherkunft bereits die Code behind-Klasse erhalten. Damit brauchen wir für das DataGrid-Element namens dgKunden nur noch das Attribut ItemsSource auf den Wert {Binding Kunden} einzustellen.

<Page x:Class="Bestellverwaltung.Kundenuebersicht" ...  xmlns:local="clr-namespace:Bestellverwaltung"
       mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Title="Kundenuebersicht">
     <Grid>
         <DataGrid x:Name="dgKunden" ItemsSource="{Binding Kunden}" AutoGenerateColumns="false">
             <DataGrid.Columns>
                 <DataGridTextColumn Binding="{Binding Path=ID}" Header="ID"  />
                 <DataGridTextColumn Binding="{Binding Path=Firma}" Header="Firma" />
                 <DataGridTextColumn Binding="{Binding Path=Vorname}" Header="Vorname"  />
                 <DataGridTextColumn Binding="{Binding Path=Nachname}" Header="Nachname" />
             </DataGrid.Columns>
         </DataGrid>
     </Grid>
</Page>

Listing 3: Code für die Definition des Page-Elements zur Anzeige der Kundenübersicht

Es verwendet dann die Auflistung Kunden aus der Klasse Kunden-uebersicht.xaml.cs als Datenquelle. Die Spalten sollen nicht automatisch erstellt werden, daher erhält AutoGenerateColumns den Wert false. Die Spalten legen wir unterhalb des Elements DataGrid.Columns an, und zwar als DataGridTextColumn-Elemente. Hier erhalten diese per Binding eine Verknüpfung zum jeweiligen Feld der Datenherkunft sowie per Header eine Spaltenüberschrift. Das Ergebnis soll anschließend wie in Bild 4 aussehen.

Das Page-Element mit den Kundendaten im Frame-Element des Window-Objekts

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins DATENBANKENTWICKLER:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 200 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar