Seminarverwaltung IVa: Kunden und Seminare

Die Arbeit mit der Seminarverwaltung startet an dem Punkt, wo wir die online eingegangenen Bestellungen einlesen und in der Seminarverwaltung Kunden und Bestellungen in Kunden und Seminarteilnahmen umwandeln. Dazu benötigen wir eine Möglichkeit, die online erfolgten Bestellungen in die Anwendung einzulesen – siehe Artikel “Seminarverwaltung VI: Daten vom Shopsystem”. Außerdem wollen wir in diesem Artikel zeigen, wie Sie die Kunden und die Seminarteilnahmen verwalten können. Hier kann es auch vorkommen, dass ein Kunde auf einem anderen Wege als im Onlineshop bestellt – daher benötigen wir Möglichkeit zum Anlegen von Kunden und Seminarteilnahmen über die Benutzeroberfläche.

Wir haben diesen Artikel gegenüber der ursprünglichen Planung dreigeteilt. Den ersten Teil finden Sie hier vor, den zweiten und dritten Teil beschreiben wir gleich im Anschluss. In diesem Teil der Artikelreihe zeigen wir, wie Sie die Seiten zum Verwalten von Kunden und Seminaren und der Zuordnung von Kunden zu Seminaren und umgekehrt realisieren können. Dazu legen wir jeweils Page-Elemente an, und zwar die folgenden:

  • KundenUebersicht.xaml: Diese Seite zeigt eine Liste aller Kunden an und bietet die Möglichkeit, die Kunden nach verschiedenen Kriterien zu durchsuchen. Außerdem enthält sie Schaltflächen zum Anlegen neuer Kunden, zum Löschen von Kunden und zum Bearbeiten eines Kunden.
  • Kundendetails.xaml: Diese Seite zeigt die Details zu einem Kunden an. Dazu gehören neben den Daten der Tabelle tblKunden auch die von diesem Kunden gebuchten Seminare. Die Seite soll auch die Möglichkeit bieten, Seminare zum Kunden hinzuzufügen oder zu entfernen.

In der ersten Fortsetzung dieses Artikels namens Seminarverwaltung IVb: Kunden und Seminare (www.datenbankentwickler.net/294) schauen wir uns die Seiten zur Darstellung der Seminare in der Übersicht und in der Einzelansicht an. Die dort beschriebenen Seiten lauten:

  • SeminareUebersicht.xaml: Die Übersichtsseite für die Seminare soll eine Liste aller Seminare anzeigen. Hier soll der Benutzer eine Suchfunktion vorfinden sowie Schaltflächen zum Anlegen neuer Seminare und zum Bearbeiten oder Löschen von Seminaren.
  • Seminardetails.xaml: Die Detailseite eines Seminars zeigt neben den Details des Seminars auch eine Liste der Kunden an, die dieses Seminar gebucht haben. Sie können hier manuell Kunden hinzufügen oder aus der Liste der Teilnehmer entfernen. Außerdem finden Sie hier Funktionen, um den Kunden Informationen zum Seminar zuzusenden – beispielsweise E-Mails mit dem Link zur Teams-Sitzung, in der das Seminar stattfindet, oder für die Aufzeichnung des Seminars.

Schließlich folgt noch der dritte Teil, den wir Seminarverwaltung IVc: Kunden und Seminare (www.datenbankentwickler.net/295) genannt haben. In diesem beschreiben wir, wie wir den in den ersten beiden Teilen erläuterten Seiten noch die Elemente hinzufügen, mit denen Sie die Zuordnung von Kunden zu Seminaren verwalten können.

Die Kundenübersicht

Die Kundenübersicht soll alle Kunden in einem ListView-Steuerelement anzeigen. Außerdem wollen wir folgende Funktionen bereitstellen:

  • Öffnen der Details zu einem Kunden per Doppelklick auf den jeweiligen Eintrag
  • Öffnen der Details zu einem Kunden durch Auswahl und anschließendes Betätigen der Bearbeiten-Schaltfläche
  • Löschen des aktuell markierten Kunden per Schaltfläche
  • Anlegen eines neuen Kunden per Schaltfläche
  • Suche nach Kunden über den Vornamen und den Nachnamen

Der Entwurf dieser Seite namens Kundendetails.xaml sieht wie in Bild 1 aus.

Entwurf der Seite zur Anzeige der Kundenübersicht

Bild 1: Entwurf der Seite zur Anzeige der Kundenübersicht

Im XAML-Code haben wir ein Grid definiert, das drei Zeilen aufnimmt. Die erste enthält ein StackPanel mit den Suchfeldern, die zweite das ListView-Steuerelement und die dritte die Steuerelemente zum Verwalten der angezeigten Kunden:

<Page x:Class="KundenUebersicht" ... Title="KundenUebersicht">
     ...
     <Grid>
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto"></RowDefinition>
             <RowDefinition Height="*"></RowDefinition>
             <RowDefinition Height="Auto"></RowDefinition>
         </Grid.RowDefinitions>

Das StackPanel für die Suche definieren wir mit zwei Textfeldern zur Eingabe von Vorname und/oder Nachname und einer Schaltfläche zum Ausführen der Suche:

         <StackPanel Orientation="Horizontal">
             <Label>Vorname:</Label>
             <TextBox x:Name="txtSucheVorname" Width="100"></TextBox>
             <Label>Nachname:</Label>
             <TextBox x:Name="txtSucheNachname" Width="100"></TextBox>
             <Button x:Name="btnSuchen" Click="btnSuchen_Click">
                 <StackPanel Orientation="Horizontal">
                     <Image Source="images/find_text.png" Width="24" Height="24"></Image>
                 </StackPanel>
             </Button>
         </StackPanel>

Das ListView-Steuerelement namens lvwKunden ist an die Auflistung Kunden aus dem Code behind-Modul gebunden. Es erlaubt das Auswählen jeweils eines Elements und bei einem Doppelklick soll eine Ereignismethode ausgelöst werden. Die einzelnen anzuzeigenden Spalten definieren wir mit GridViewColumn-Elementen:

         <ListView x:Name="lvwKunden" Grid.Row="1" ItemsSource="{Binding Kunden}" SelectionMode="Single"                  MouseDoubleClick="lvwKunden_MouseDoubleClick">
             <ListView.View>
                 <GridView>
                     <GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}" />
                     <GridViewColumn Header="Firma" DisplayMemberBinding="{Binding Firma}" />
                     <GridViewColumn Header="Vorname" DisplayMemberBinding="{Binding Vorname}" />
                     <GridViewColumn Header="Nachname" DisplayMemberBinding="{Binding Nachname}" />
                     <GridViewColumn Header="Straße" DisplayMemberBinding="{Binding Strasse}" />
                     <GridViewColumn Header="PLZ" DisplayMemberBinding="{Binding PLZ}" />
                     <GridViewColumn Header="Ort" DisplayMemberBinding="{Binding Ort}" />
                     <GridViewColumn Header="Land" DisplayMemberBinding="{Binding Land}" />
                     <GridViewColumn Header="E-Mail" DisplayMemberBinding="{Binding EMail}" />
                 </GridView>
             </ListView.View>
         </ListView>

Die dritte Zeile des Grid-Elements enthält ein weiteres StackPanel-Element mit den Steuerelementen zum Verwalten der Kunden – hier mit Schaltflächen zum Schließen des Bereichs (btnOK), zum Anlegen neuer Kunden (btnNeu), zum Anzeigen des aktuellen Kunden (btnDetails) und zum Löschen des aktuell markierten Kunden (btnLoeschen):

         <StackPanel Orientation="Horizontal" Grid.Row="2">
             <Button x:Name="btnOK" Click="btnOK_Click">
                 <StackPanel Orientation="Horizontal">
                     <Image Source="images/ok.png" Width="24" Height="24"></Image>
                     <Label>OK</Label>
                 </StackPanel>
             </Button>
             <Button x:Name="btnNeu" Click="btnNeu_Click">
                 <StackPanel Orientation="Horizontal">
                     <Image Source="images/add.png" Width="24" Height="24"></Image>
                     <Label>Neu</Label>
                 </StackPanel>
             </Button>
             <Button x:Name="btnDetails" Click="btnDetails_Click">
                 <StackPanel Orientation="Horizontal">
                     <Image Source="images/pencil.png" Width="24" Height="24"></Image>
                     <Label>Bearbeiten</Label>
                 </StackPanel>
             </Button>
             <Button x:Name="btnLoeschen" Click="btnLoeschen_Click">
                 <StackPanel Orientation="Horizontal">
                     <Image Source="images/delete.png" Width="24" Height="24"></Image>
                     <Label>Löschen</Label>
                 </StackPanel>
             </Button>
         </StackPanel>
     </Grid>
</Page>

Anzeigen der Kunden im ListView-Steuerelement

Im Code behind-Modul benötigen wir den folgenden Namespace-Verweis:

Imports System.Collections.ObjectModel

Außerdem deklarieren wir hier die folgenden Variablen:

Private dbContext As New SeminarverwaltungContext
Private _kunden As ObservableCollection(Of Kunde)
Private objFrame As Frame
Private objListCollectionView As ListCollectionView

Beim Initialisieren der Seite wird die Konstruktor-Methode ausgelöst. Diese erwartet als Parameter einen Verweis auf das übergeordnete Frame-Element, beispielsweise zum Leeren des Frame-Elements, wenn die Seite geschlossen wird. Diesen Verweis speichert die Prozedur in der Variablen objFrame. Außerdem initialisiert die Methode die Komponente (InitializeComponent), füllt die Liste der Kunden, weist sich selbst dem DataContext zu und referenziert mit objListCollectionView eine Sicht auf die Auflistung Kunden. Schließlich stellt sie die Methode Kundenfilter als auszuführende Methode beim Aufruf des Filters der ListCollectionView ein:

Public Sub New(fra As Frame)
     objFrame = fra
     InitializeComponent()
     Kunden = New ObservableCollection(Of Kunde)(dbContext.Kunden)
     DataContext = Me
     objListCollectionView = CollectionViewSource.GetDefaultView(Kunden)
     objListCollectionView.Filter = AddressOf Kundenfilter
End Sub

Die öffentliche Eigenschaft Kunden erfasst die Auflistung der Kunden und stellt diese als Quelle für das ListView-Steuerelement zur Verfügung:

Public Property Kunden As ObservableCollection(Of Kunde)
     Get
         Return _kunden
     End Get
     Set(value As ObservableCollection(Of Kunde))
         _kunden = value
     End Set
End Property

Filtern nach dem Vornamen und dem Nachnamen

Die Steuerelemente im oberen Bereich der Kundenübersicht erlauben die Eingabe eines Vornamens und einen Nachnamens, nach dem gefiltert werden soll. Für die Eigenschaft Filter des ListCollectionView-Elements haben wir weiter oben bereits die Funktion Kundenfilter zugewiesen. Die Funktion Kundenfilter wird beim Filtern der ListCollectionView für jeden Datensatz einmal aufgerufen. Dabei erfasst sie den Vornamen und den Nachnamen des aktuellen Kunde-Elements und schreibt diese beziehungsweise gegebenenfalls eine leere Zeichenkette in die Variablen strVorname und strNachname. Dann prüft sie, ob Nachname und Vorname mit den Werten aus txtSucheNachname beziehungsweise txtSucheVorname beginnen. Falls nicht, wird der Wert False zurückgegeben. Ist beides erfüllt, gibt die Funktion den Wert True zurück und des jeweilige Element wird angezeigt:

Private Function Kundenfilter(item As Object) As Boolean
     Dim objKunde As Kunde
     Dim strVorname As String
     Dim strNachname As String
     objKunde = TryCast(item, Kunde)
     strVorname = IIf(objKunde.Vorname = Nothing, "", objKunde.Vorname)
     strNachname = IIf(objKunde.Nachname = Nothing, "", objKunde.Nachname)
     If Not (strNachname.StartsWith(txtSucheNachname.Text, StringComparison.OrdinalIgnoreCase)) Then
         Return False
     End If
     If Not (strVorname.StartsWith(txtSucheVorname.Text, StringComparison.OrdinalIgnoreCase)) Then
         Return False
     End If
     Return True
End Function

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