Onlinebanking mit DDBAC: Benutzeroberfläche

Nachdem wir die Funktionen zum Abrufen von Kontoständen und Umsätzen sowie für das Überweisen programmiert haben, können wir uns an den Entwurf einer Benutzeroberfläche für diese Funktionen begeben. Diese soll kompakte Formulare für die wichtigsten bereits behandelten Onlinebanking-Funktionen enthalten. Dazu gehört die Auswahl von Bankaccount und Konto sowie die Anzeige von Umsätzen und Kontostand. Dies erledigen wir im Hauptfenster der Anwendung. Ein weiteres Fenster erlaubt dann das Ausführen einer Überweisung für das aktuell im Hauptfenster ausgewählte Konto. Außerdem benötigen wir noch eine Tabelle, mit der wir die abgefragten Umsatzdaten speichern können. Diese fügen wir per Entity Framework hinzu.

Voraussetzungen

Voraussetzung für das Umsetzen der Lösung dieses Artikels ist das Vorhandensein einer DDBAC-Lizenz. Die damit nutzbaren Komponenten sind leider nicht mehr kostenlos verfügbar, sondern müssen lizensiert werden, bevor man diese in seine Produkte einbauen kann. Lizenzen finden Sie im Onlineshop unter https://shop.minhorst.com/access-tools/295/ddbac-jahreslizenzc=78.

Vorbereitungen

Als Projekt legen wir ein neues Projekt des Typs Visual Basic|Windows Desktop|WPF-App an.

Dann fügen wir ein neues Element des Typs ADO.NET Entity Data Model hinzu. Dieses dient dazu, ein Entity Data Model zu erstellen und über dieses automatisch eine Datenbank mit der benötigten Tabelle zu generieren. Nachdem Sie mit dem Menü-befehl Projekt|Neues Element hinzufügen… den Dialog Neues Element hinzufügen geöffnet haben, tragen Sie den Namen des Entity Data Models ein (hier OnlinebankingContext) und klicken auf Hinzufügen. Im nun erscheinenden Assistent für Entity Data Model wählen Sie den Typ Leeres Code First-Modell aus. Wenige Sekunden später hat der Assistent die notwendigen Elemente hinzugefügt.

Durch diesen Schritt haben wir außerdem direkt Änderungen an der Datei App.config vorgenommen. Dort steht nun im Element connectionStrings die Verbindungszeichenfolge, mit der wir später die Datenbank zum Speichern der Umsätze erstellen und verwenden.

Außerdem benötigen wir noch eine Referenz auf die DDBAC-Komponenten, die den Zugriff auf Ihre Konten überhaupt erst ermöglichen. Dazu fügen Sie dem Projekt den Verweis aus Bild 1 hinzu.

Verweis auf die DDBAC-Bibliothek

Bild 1: Verweis auf die DDBAC-Bibliothek

Kontostand anzeigen

Wir beginnen mit der Anzeige des Kontostands. Hier wollen wir in einem Fenster die Auswahl des Kontakts und anschließend des gewünschten Kontos erlauben. Per Klick auf eine Schaltfläche soll dann der Kontostand eingelesen und in einem Textfeld angezeigt werden. Wie Sie bereits in den vorherigen Artikeln erfahren haben, legen wir die Kontakte und Konten über die Systemsteuerung an, und zwar über die App Homebanking Administrator (32-Bit). Auf die dort angelegten und synchronisierten Elemente können wir dann per Code zugreifen.

Ein neues WPF-Fenster soll nun zunächst ein Kombinationsfeld zur Auswahl des Kontakts anbieten. Nachdem der Benutzer dort einen Eintrag ausgewählt hat, sollen die zum gewählten Kontakt gehörenden Konten in einem zweiten Kombinationsfeld angezeigt werden. Das passende Steuer-element für diesen Zweck ist jeweils das ComboBox-Element. Also fügen wir zunächst zwei solche Elemente im Hauptfenster MainWindow.xaml an. Damit die zusätzlich angelegten Bezeichnungsfelder optisch ansprechend dargestellt werden, erstellen wir zuvor einige Spalten und Zeilen im bereits vorhandenen Grid-Element.

Klasse für die Kontakte anlegen

Die über die Systemsteuerung hinzufügten Onlinebanking-Kontakte lesen wir mithilfe der im Artikel Onlinebanking mit DDBAC: Saldo und Umsätze beschriebenen Funktion ein, die wir jedoch leicht abwandeln. Die eingelesenen Daten sollen je Kontakt in einer neuen Instanz der nachfolgend beschriebenen Klasse landen:

Public Class Contact
     Public BankCode As String
     Public CountryCode As String
     Public UserID As String
End Class

Diese Klasse legen Sie als neues Element im Projekt an und speichern es unter Contact.vb. Wir benötigen allerdings die INotifyPropertyChanged-Schnittstelle in dieser Klasse, daher ändern wir diese wie folgt.

Wir fügen außerdem noch eine Eigenschaft namens BACContact hinzu, mit der wir einen Verweis auf das BACContact-Objekt speichern, aus dem wir die Eigenschaften der Klasse ausgelesen haben:

Imports System.ComponentModel
Public Class Contact
     Implements INotifyPropertyChanged
     Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
     Protected Overridable Sub OnPropertyChanged(propname As String)
         RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propname))
     End Sub
     Private _bankCode As String
     Private _countryCode As String
     Private _userID As String
     Private _bACContact As BACContact
     Public Property BankCode As String
         Get
             Return _bankCode
         End Get
         Set(value As String)
             _bankCode = value
             OnPropertyChanged("BankCode")
         End Set
     End Property
     Public Property CountryCode As String
         Get
             Return _countryCode
         End Get
         Set(value As String)
             _countryCode = value
             OnPropertyChanged(CountryCode)
         End Set
     End Property
     Public Property UserID As String
         Get
             Return _userID
         End Get
         Set(value As String)
             _userID = value
             OnPropertyChanged("UserID")
         End Set
     End Property
     Public Property BACContact As BACContact
         Get
             Return _bACContact
         End Get
         Set(value As BACContact)
             _bACContact = value
         End Set
     End Property
End Class

Klasse für die Konten anlegen

Die Klasse für die Konten sieht ähnlich aus wie die für die Kontakte. Auch hier implementieren wir die INotifyPropertyChanges-Schnittstelle. Die Klasse bietet die Eigenschaften AccountNumber, AcctName, BIC und IBAN an. Darüberhinaus wollen wir das BACAccount-Objekt, über das wir die Klasse füllen, mit den Instanzen der Klasse speichern. Die Klassendefinition sieht wie folgt aus:

Imports System.ComponentModel
Imports BankingApplicationComponents
Public Class Account
     Implements INotifyPropertyChanged
     Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
     Protected Overridable Sub OnPropertyChanged(propname As String)
         RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propname))
     End Sub
     Private _accountNumber As String
     Private _acctName As String
     Private _bIC As String
     Private _iBAN As String
     Private _bACAccount As BACAccount
     Public Property AccountNumber As String
         Get
             Return _accountNumber
         End Get
         Set(value As String)
             _accountNumber = value
             OnPropertyChanged("AccountNumber")
         End Set
     End Property
     ... weitere Property-Eigenschaften
     Public Property BACAccount As BACAccount
         Get
             Return _bACAccount
         End Get
         Set(value As BACAccount)
             _bACAccount = value
         End Set
     End Property
End Class

Auflistung mit Kontakt-Elementen füllen

Wenn die Anwendung gestartet und somit das Fenster MainWindow.xaml geöffnet wird, sollen die Kontakte aus der Systemsteuerung eingelesen und in jeweils eine neue Klasse des Typs Contact geschrieben werden. Die neuen Instanzen wollen wir außerdem direkt zu einer Liste hinzufügen, die wir anschließend dem ersten ComboBox-Element zuweisen können. Wir nutzen dazu eine Funktion namens GetBACContacts, die eine Liste von Elementen des Typs BACContact liefert. Diese fügen wir einem Modul namens DDBACObjects.vb hinzu, dem wir außerdem noch per Imports-Anweisung die Elemente des Namespace BankingApplicationComponents hinzufügen.

Die folgende privat deklarierte Variable speichert die Contacts-Auflistung zwischen, damit diese nicht bei jedem Zugriff erneut ausgelesen werden müssen:

     Private m_Contacts As BACContacts

Die Funktion GetBACContacts liest die Kontakte mit den Methoden der DDBAC-Bibliothek aus der Systemsteuerung in die Variable m_BACContacts ein. Diese wird dann anschließend auch als Ergebnis der Funktion zurückgegeben. Wenn m_BACContacts bereits vorhanden ist, wird die Auflistung nicht erneut gefüllt. Einzige Ausnahme ist, wenn der Aufruf den Wert True für den Parameter bolReset enthält. In diesem Fall werden die Kontakte auf jeden Fall erneut eingelesen:

Public Function GetBACContacts(Optional bolReset As Boolean = False) As BACContacts
     If m_BACContacts Is Nothing Then
         m_BACContacts = New BACContacts
         m_BACContacts.Populate("")
     Else
         If bolReset = True Then
             m_BACContacts.Populate("")
         End If
     End If
     Return m_BACContacts
End Function

Damit haben wir mit GetBACContacts eine Liste der BACContact-Elemente eingelesen. Diese müssen wir nun noch in eine ObservableCollection mit Elementen des oben definierten Typs Contact umfüllen. Diese Liste wollen wir dann als Datenquelle des ersten ComboBox-Elements in unserem Fenster verwenden. Diese Aufgabe übernimmt die Funktion GetContacts. Sie erstellt eine neue ObservableCollection in der Variablen objContacts. Dann durchläuft sie eine For Each-Schleife über alle BACContact-Elemente, welche die oben beschriebene Funktion GetContacts liefert. Innerhalb der Schleife legt sie ein neues Contact-Element an (nicht zu verwechseln mit BACContact), und schreibt die entsprechenden Werte in die Eigenschaften BankCode, CountryCode und UserID sowie einen Verweis auf das aktuelle BACContact-Objekt in die Eigenschaft BACContact. Anschließend fügt sie das neu erstellte und gefüllte Objekt zur ObservableCollection hinzu:

Public Function GetContacts() As ObservableCollection(Of Contact)
     Dim objContacts As ObservableCollection(Of Contact)
     Dim objContact As Contact
     Dim objBACContact As BACContact
     objContacts = New ObservableCollection(Of Contact)
     For Each objBACContact In GetBACContacts()
         objContact = New Contact
         With objContact
             .BankCode = objBACContact.BankCode
             .CountryCode = objBACContact.CountryCode
             .UserID = objBACContact.UserID
             .BACContact = objBACContact
             objContacts.Add(objContact)
         End With
     Next
     Return objContacts
End Function

Auflistung für die Konten füllen

Wenn der Benutzer in der gleich noch zu erstellenden ComboBox einen Kontakt ausgewählt hat, soll die zweite ComboBox die zu diesem Kontakt gehörenden Konten zur Auswahl anbieten. Deshalb benötigen wir analog zu den oben beschriebenen Funktionen GetBACContacts und GetContacts eine weitere Funktion.

Die Funktion GetBACAccounts erwartet als Parameter ein BACContact-Objekt, zu dem sie die BACAccount-Objekte einlesen soll. Sie verwendet dann schlicht die Accounts-Auflistung des BACContact-Objekts, um die Liste in der Variablen m_Accounts des Typs BACAccounts zu speichern:

Public Function GetBACAccounts(objBACContact As BACContact) As BACAccounts
     Return objBACContact.Accounts
End Function

Wenn der Benutzer im ersten ComboBox-Feld mit den Kontakten einen Eintrag ausgewählt hat, holen wir mit der folgenden Funktion die Daten zum Füllen des zweiten ComboBox-Feldes zur Anzeige der Konten dieses Kontakts. Dabei verwenden wir auch hier als Parameter das BACContact-Element des zu untersuchenden Kontaktes. Die Funktion erstellt als Erstes wieder eine neue ObservableCollection.

In einer For Each-Schleife durchlaufen wir diesmal die mit der Funktion GetBACAccounts geholten Konten. Innerhalb der For Each-Schleife legen wir ein neues Objekt des Typs Account an und weisen diesem die Werte für die Eigenschaften AccountNumber, AcctName, IBAN und BIC zu sowie einen Verweis auf das BACAccount-Objekt dieses Kontos. Anschließend fügen wir es der ObservableCollection namens objAccounts zu, die wir als Funktionsergebnis zurückliefern:

Public Function GetAccounts(objBACContact As BACContact) As ObservableCollection(Of Account)
     Dim objAccounts As ObservableCollection(Of Account)
     Dim objAccount As Account
     Dim objBACAccount As BACAccount
     objAccounts = New ObservableCollection(Of Account)
     For Each objBACAccount In GetBACAccounts(objBACContact)
         objAccount = New Account
         With objAccount
             .AccountNumber = objBACAccount.AccountNumber
             .AcctName = objBACAccount.AcctName
             .BIC = objBACAccount.BIC
             .IBAN = objBACAccount.IBAN
             .BACAccount = objBACAccount
         End With
         objAccounts.Add(objAccount)
     Next
     Return objAccounts
End Function

Fenster zur Anzeige der Auswahlfelder für Kontakte und Konten

Das Fenster soll im oberen Bereich zwei ComboBox-Elemente zur Auswahl von Kontakten und Konten anzeigen. Im Kontakt-Kombinationsfeld wollen wir die UserID und die Bankleitzahl anzeigen. Das Konto-Auswahlfeld soll nur die IBAN anzeigen. Die Definition dieser beiden Steuer-elemente sieht wie folgt aus. Als Erstes das ComboBox-Element cboContacts, das an die Auflistung Contacts gebunden ist, die wir gleich noch im Code behind-Modul definieren.

Das ComboBox-Element hat außerdem ein Attribut für das Ereignis SelectionChanged. Da wir zwei Felder im ComboBox-Element anzeigen wollen, stellen wir diese in einem ItemTemplate und den entsprechenden untergeordneten Elementen wie folgt dar:

<Label Grid.Column="0" Content="Kontakt:"/>
<ComboBox x:Name="cboContacts" Grid.Row="0" Grid.Column="1" Width="200"
             ItemsSource="{Binding Contacts}"
             SelectedValuePath="UserID"
             SelectionChanged="CboContacts_SelectionChanged">
     <ComboBox.ItemTemplate>
         <DataTemplate>
             <TextBlock>
                 <TextBlock.Text>
                     <MultiBinding StringFormat="{}{0} {1}">
                         <Binding Path="UserID" />
                         <Binding Path="BankCode" />
                     </MultiBinding>
                 </TextBlock.Text>
             </TextBlock>
         </DataTemplate>
     </ComboBox.ItemTemplate>
</ComboBox>

Das zweite ComboBox-Element für die Konten ist an die Liste Accounts gebunden. Sie soll nur das Feld IBAN anzeigen und löst ebenfalls das Ereignis SelectionChanged aus:

<Label Grid.Column="0" Grid.Row="1" Content="Konto:"/>
<ComboBox x:Name="cboAccounts" Grid.Row="1" Grid.Column="1" Width="200"
             ItemsSource="{Binding Accounts}"
             SelectedValuePath="IBAN"
             SelectionChanged="CboAccounts_SelectionChanged"
             DisplayMemberPath="IBAN">
</ComboBox>

Code behind-Klasse des Fensters

Die Code behind-Klasse verwendet die folgenden beiden Namespaces:

Imports System.Collections.ObjectModel
Imports System.ComponentModel

Außerdem implementiert sie die INotifyPropertyChanged-Schnittstelle:

Class MainWindow
     Implements INotifyPropertyChanged
     Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
     Protected Overridable Sub OnPropertyChanged(propname As String)
         RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propname))
     End Sub

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Visual Basic Entwickler:
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