{"id":55000265,"date":"2005-02-01T00:00:00","date_gmt":"2020-05-06T15:17:56","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=265"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Adressverwaltung_mit_NET_Teil_2","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/","title":{"rendered":"Adressverwaltung mit .NET, Teil 2"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/3af6b630ea33483fa9969e6e1e4dec30\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Manfred Hoffbauer, D&uuml;sseldorf<\/b><\/p>\n<p><b>Im ersten Teil dieses Beitrags haben Sie die Adressen aus einer Access-Datenbank in ein DataGrid-Steuerelement geladen. In diesem zweiten Teil steigen Sie tiefer in die Programmierung ein und erfahren, wie Sie Adressen aus einem Listensteuerelement ausw&auml;hlen und komfortabel in der Einzelansicht bearbeiten k&ouml;nnen.<\/b><\/p>\n<p>Die folgenden Beispiele und Vorgehensweisen k&ouml;nnen Sie mit der kostenlosen Entwicklungsumgebung SharpDevelop nachvollziehen. Alternativ l&auml;sst sich der Programmcode nat&uuml;rlich auch in einem Microsoft-Visual-Studio.NET-Projekt verwenden.<\/p>\n<p>Das Ziel dieses Beitrags ist ein Formular zur Eingabe und Bearbeitung von Adressen. Es enth&auml;lt ein Listenfeld mit einer &uuml;bersicht der Adressen. Jede einzelne Adresse kann mit der Maus angeklickt und bearbeitet werden. Auch das Hinzuf&uuml;gen und L&ouml;schen von Adressen ist implementiert. Das Formular soll wie in Bild 1 aussehen.<\/p>\n<p><IMG height=\"289\" src=\"..\/fileadmin\/_temp_\/{8FB327D6-6197-4E11-9099-0FC6907FEBCF}\/pic001.png\" width=\"500\" border=\"0\"><\/p>\n<p><b><\/b><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1:  Formular zur Eingabe und Bearbeitung von Adressen<\/span><\/b><\/p>\n<p>Zur Eingabe und Bearbeitung der Adressen legen Sie ein Formular mit Einzelsatzansicht an. Gehen Sie dazu wie folgt vor:<\/p>\n<li>W&auml;hlen Sie den Men&uuml;punkt Datei ( Neu ( Combine aus der Men&uuml;zeile.<\/li>\n<li>W&auml;hlen Sie ein Verzeichnis f&uuml;r das neue Projekt aus.<\/li>\n<li>Geben Sie WinAdress2 als Dateinamen f&uuml;r das neue Projekt ein.<\/li>\n<li>Markieren Sie die Schablone Windows-Anwendung.<\/li>\n<li>Klicken Sie auf Erstellen. (<\/li>\n<h2>Das Formular benennen<\/h2>\n<p>SharpDevelop generiert den Programmcode f&uuml;r ein neues, leeres Formular und speichert ihn unter dem Namen MainForm.vb. Mit den Registern Quellcode und Design wechseln Sie zwischen der Ansicht des Programmcodes und der Anzeige des Formularentwurfs.<\/p>\n<p>Um den Namen des Formulars zu &auml;ndern, gehen Sie wie folgt vor:<\/p>\n<li>Wechseln Sie in die Design-Ansicht des Formulars.<\/li>\n<li>Klicken Sie mit der rechten Maustaste auf einen leeren Bereich des Formulars.<\/li>\n<li>W&auml;hlen Sie den Men&uuml;punkt Eigenschaften aus dem Kontextmen&uuml;.<\/li>\n<li>Um die Titelzeile des Formulars zu &auml;ndern, geben Sie f&uuml;r die Eigenschaft Text den Wert Adressen ein.<\/li>\n<li>&auml;ndern Sie die Eigenschaft Name des Formulars auf frmAdressen. (<\/li>\n<p>Beachten Sie, dass Sie mit dem Eigenschaftenfenster nur die Name-Eigenschaft des Formulars und die Titelzeile &auml;ndern k&ouml;nnen. SharpDevelop speichert den Programmcode weiterhin in der Datei MainForm.vb. Um den Namen der Formulardatei zu &auml;ndern, gehen Sie wie folgt vor:<\/p>\n<li>Klicken Sie im unteren Register des SharpDevelop-Fensters auf die Lasche Projekte.<\/li>\n<li>Klicken Sie im Projekt-Explorer auf den Eintrag MainForm.vb.<\/li>\n<li>Bet&auml;tigen Sie die Taste F2 und benennen Sie die Datei in frmAdressen.vb um. (<\/li>\n<p>Der urspr&uuml;ngliche Name MainForm kommt jetzt immer noch als Klassenname innerhalb des Quellcodes vor. Falls Sie auch dies noch &auml;ndern wollen, m&uuml;ssen Sie die Zeile<\/p>\n<pre>Public Class MainForm<\/pre>\n<p>in<\/p>\n<pre>Public Class Adressen<\/pre>\n<p>umwandeln. Au&szlig;erdem m&uuml;ssen Sie die Prozedur anpassen, die das Startformular der Anwendung instanziert:<\/p>\n<pre>Public Shared Sub Main\r\n    Dim fAdressen As New Adressen\r\n    fAdressen.ShowDialog()\r\nEnd Sub<\/pre>\n<h2>Steuerelemente anordnen<\/h2>\n<p>Das Formular soll ein ListView-Steuerelement erhalten, das eine Liste aller Adressen anzeigt. Um die Liste anzulegen, klicken Sie am linken unteren Rand des SharpDevelop-Fensters auf die Registerlasche Tools. Markieren Sie in der Toolbox die Gruppe Windows Forms. Ziehen Sie dann das ListView-Steuerelement auf den Entwurfsbereich. Im Eigenschaftenfenster sollten Sie den Namen des Steuerelements auf lstvAdressen &auml;ndern.<\/p>\n<p>Die weiteren Eigenschaften des ListView-Steuerelements k&ouml;nnen Sie so lassen wie sie sind. Sie werden sp&auml;ter per Programmcode ver&auml;ndert. Zur Anzeige der Adressen in der Einzelansicht ben&ouml;tigen Sie die Label-Steuerelemente aus Tab. 1.<\/p>\n<table border=1>\n<tr>\n<td>\n<p><b>Label-Name<\/b><\/p>\n<\/td>\n<td>\n<p><b>Text<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>lblAnrede<\/p>\n<\/td>\n<td>\n<p>Anrede<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>lblVorname<\/p>\n<\/td>\n<td>\n<p>Vorname<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>lblNachname<\/p>\n<\/td>\n<td>\n<p>Nachname<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>lblStrasse<\/p>\n<\/td>\n<td>\n<p>Strasse<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>lblPlzOrt<\/p>\n<\/td>\n<td>\n<p>PLZ\/Ort<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>lblTelefon<\/p>\n<\/td>\n<td>\n<p>Telefon<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>lblTelefax<\/p>\n<\/td>\n<td>\n<p>Telefax<\/p>\n<\/td>\n<\/tr>\n<\/table>\n<p><b>Tab. 1: Diese Label-Steuerelemente sind erforderlich.<\/b><\/p>\n<p>Die Anzeige und Bearbeitung der Daten erfolgt in Text- und Kombinationsfeldern. Tab. 2 enth&auml;lt eine &uuml;bersicht der erforderlichen Steuerelemente.<\/p>\n<table border=1>\n<tr>\n<td>\n<p><b>Name<\/b><\/p>\n<\/td>\n<td>\n<p><b>Steuerelementtyp<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>cmbAnredeID<\/p>\n<\/td>\n<td>\n<p>ComboBox<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>txtVorname<\/p>\n<\/td>\n<td>\n<p>TextBox<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>txtNachname<\/p>\n<\/td>\n<td>\n<p>TextBox<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>txtStrasse<\/p>\n<\/td>\n<td>\n<p>TextBox<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>txtPLZ<\/p>\n<\/td>\n<td>\n<p>TextBox<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>txtOrt<\/p>\n<\/td>\n<td>\n<p>TextBox<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>txtTelefon<\/p>\n<\/td>\n<td>\n<p>TextBox<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>txtTelefax<\/p>\n<\/td>\n<td>\n<p>TextBox<\/p>\n<\/td>\n<\/tr>\n<\/table>\n<p><b>Tab. 2: Diese Kombinations- und Textfelder sind erforderlich.<\/b><\/p>\n<p><IMG height=\"370\" src=\"..\/fileadmin\/_temp_\/{8FB327D6-6197-4E11-9099-0FC6907FEBCF}\/pic002.png\" width=\"500\" border=\"0\"><\/p>\n<p><b><\/b><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2:  Die Abbildung zeigt die Steuerelemente zur Anzeige und Bearbeitung von Adressen.<\/span><\/b><\/p>\n<p>Das Hinzuf&uuml;gen der Steuerelemente erfolgt &uuml;ber die Toolbox. Ordnen Sie die Steuerelemente stets paarweise so an, dass eine Einzelsatzansicht wie in Bild 2 entsteht.<\/p>\n<p>Zum Test k&ouml;nnen Sie das Programm per F5-Taste starten. Sie werden dabei feststellen, dass es vollst&auml;ndig kompiliert und ausgef&uuml;hrt werden kann. Nur das Ergebnis ist vielleicht etwas ern&uuml;chternd. Sie erhalten ein Formular v&ouml;llig ohne Funktionalit&auml;t, das noch nicht einmal einen Datensatz anzeigen kann. Dies verdeutlicht einen wichtigen Unterschied zwischen Microsoft Access und einem .NET-Programm: Bei .NET m&uuml;ssen Sie jede einzelne Programmfunktion selbst programmieren. Wenn Sie also einen Datensatz anzeigen wollen, dann ben&ouml;tigen Sie zun&auml;chst einmal ein Programm, das per OleDB auf eine Access-Datenbank zugreift.<\/p>\n<p>Die Routinen f&uuml;r den Datenzugriff sollen in der Klasse DataLayer zusammengefasst werden.<\/p>\n<p>Zum Anlegen der Klasse gehen Sie wie folgt vor:<\/p>\n<li>W&auml;hlen Sie den Befehl Ansicht\/Projekte aus der Men&uuml;zeile.<\/li>\n<li>Klicken Sie mit der rechten Maustaste auf das Projekt WinAdress2.<\/li>\n<li>W&auml;hlen Sie den Befehl Hinzuf&uuml;gen\/Neue Datei aus dem Kontextmen&uuml;.<\/li>\n<li>Markieren Sie in dem sich &ouml;ffnenden Dialog die Kategorie VB und die Schablone Klasse. <\/li>\n<li>Geben Sie DataLayer als Namen der Klasse ein.<\/li>\n<li>Klicken Sie auf die Schaltfl&auml;che Erstellen. (<\/li>\n<p>SharpDevelop erzeugt darauf eine neue Klassendatei und f&uuml;gt diese dem aktuellen Projekt hinzu. Sie ersetzen den Programmcode vollst&auml;ndig durch eigenen Programmcode. Mit der ersten Anweisung importieren Sie den Namenspace System.Data.OleDb. Im Beitrag ADO.NET &#8211; eine Einf&uuml;hrung in Ausgabe 5\/2004 von Access im Unternehmen finden Sie weitere Details zum Namespace OleDb. Er enth&auml;lt auf jeden Fall die f&uuml;r den Datenzugriff ben&ouml;tigten Objekte.<\/p>\n<p>Die Prozedur New ist der Konstruktor der Klasse DataLayer. Der enthaltene Programmcode wird immer dann ausgef&uuml;hrt, wenn Sie ein neues Objekt dieser Klasse instanzieren. Der Konstruktor ist so definiert, dass die aufrufende Anweisung immer einen ConnectionString angeben muss. Die New-Prozedur weist den String einer Variablen zu, die von allen Methoden der Klasse verwendet werden kann.<\/p>\n<p>Die DataLayer-Klasse implementiert das IDisposable-Interface. Die Implementation befindet sich in der Dispose()-Klasse. Sie schlie&szlig;t die Connection. Mit dieser Art der Implementierung erreichen Sie, dass die Connection per Dispose() von einer aufrufenden Methode und automatisch von der .NET-Runtime-Umgebung aufgerufen werden kann. Durch die Pr&uuml;fung Not m_Cnn Is Nothing ist in jedem Fall sichergestellt, dass die Connection nur einmal geschlossen wird.<\/p>\n<pre>Imports System.Data.OleDb\r\nPublic Class DataLayer\r\n    Implements System.IDisposable\r\n    Dim m_CnnString As String \r\n    Dim m_Cnn As OleDbConnection\r\n    Public Sub New(ByVal ConnectionString As String)\r\n        m_CnnString = ConnectionString\r\n    End Sub\r\n    Public Sub Dispose() \r\n        Implements System.IDisposable.Dispose\r\n        If Not m_Cnn Is Nothing Then\r\n            m_Cnn.Close()\r\n            m_Cnn.Dispose()\r\n            m_Cnn = Nothing\r\n        End If\r\n    End Sub\r\n    Private Function OpenConnection() As OleDbConnection\r\n        If m_Cnn Is Nothing Then\r\n            m_Cnn = New OleDbConnection(m_CnnString)\r\n            m_Cnn.Open()\r\n        End If\r\n    End Function<\/pre>\n<p><b>Quellcode 1<\/b><\/p>\n<pre>Public Function GetAnreden() As DataTable\r\n    OpenConnection()\r\n    Dim tblAnreden As New DataTable\r\n    Dim sb As New System.Text.StringBuilder\r\n    sb.Append(\"SELECT tblAnreden.* FROM tblAnreden \")\r\n    Dim adp As New OleDbDataAdapter(sb.ToString(), _        m_Cnn)\r\n    adp.Fill(tblAnreden)\r\n    adp.Dispose()\r\n    Return tblAnreden\r\nEnd Function<\/pre>\n<p><b>Quellcode 2<\/b><\/p>\n<p>Die Funktion OpenConnection &ouml;ffnet die Connection zu einer Access-Datenbank (s. Quellcode 1). Der R&uuml;ckgabewert der Funktion ist das ge&ouml;ffnete OleDbconnection-Objekt.<\/p>\n<h2>Daten lesen<\/h2>\n<p>Auf der Basis des Connection-Objekts k&ouml;nnen die DataLayer-Funktionen direkt auf die Tabellen der Access-Datenbank zugreifen. Die Funktion GetAnreden &ouml;ffnet die Connection (s. Quellcode 2). Das StringBuilder-Objekt ist ein performanter Weg f&uuml;r den Zusammenbau von Zeichenketten. Die Append-Methode f&uuml;gt ganz einfach den als Parameter &uuml;bergebenen String an die bestehende Zeichenkette an. Die so zusammengesetzte SELECT-Anweisung kann zum Auff&uuml;llen eines DataAdapter-Objekts verwendet werden. Die R&uuml;ckgabe der gelesenen Anreden erfolgt in Form eines DataTable-Objekts.<\/p>\n<p>Die GetAdressen-Funktion funktioniert genauso wie die GetAnreden-Funktion. Nur die SELECT-Anweisung ist etwas aufw&auml;ndiger (s. Quellcode 3). Sie stellt eine relationale Beziehung zwischen tblAdressen und tblAnreden her. Das entstehende DataTable-Objekt enth&auml;lt zus&auml;tzlich zu den Adressen ein Feld f&uuml;r die Anrede.<\/p>\n<h2>Adressen anlegen, &auml;ndern und l&ouml;schen<\/h2>\n<p>Die AddAdress-Funktion verwendet ebenfalls ein StringBuilder-Objekt zur Bildung einer SQL-Anweisung (s. Quellcode 4). In diesem Fall handelt es sich um eine INSERT-INTO-Anweisung, die die Anlage eines neuen Datensatzes erm&ouml;glicht. Die Parameterliste der Funktion enth&auml;lt eine Variable f&uuml;r jedes Feld, das an die tblAdressen-Tabelle angef&uuml;gt werden soll.<\/p>\n<p>Eine Besonderheit ist das Feld AnredeID. Wenn es den Wert 0 hat, dann soll dies als &#8222;keine Anrede&#8220; interpretiert werden. In diesem Fall f&uuml;gt die AddAdress-Funktion einen NULL-Wert in die Tabelle ein.<\/p>\n<p>Auf die AddAdress-Funktion folgen die UpdateAddress- und die DeleteAdress-Funktionen.<\/p>\n<pre>Public Function GetAdressen() As DataTable\r\n    OpenConnection()\r\n    Dim tblAdressen As New DataTable\r\n    Dim sb As New System.Text.StringBuilder\r\n    sb.Append(\"SELECT tblAdressen.*, tblAnreden.Anrede FROM tblAnreden \")\r\n    sb.Append(\"RIGHT JOIN tblAdressen ON tblAnreden.AnredeID = tblAdressen.AnredeID;\")\r\n    Dim adp As New OleDbDataAdapter(sb.ToString(), m_Cnn)\r\n    adp.Fill(tblAdressen)\r\n    adp.Dispose()\r\n    Return tblAdressen\r\nEnd Function<\/pre>\n<p><b>Quellcode 3<\/b><\/p>\n<pre>Public Function AddAdress(ByVal AnredeID As Integer, ByVal Vorname As String, _\r\n    ByVal Nachname As String, ByVal Strasse As String, ByVal PLZ As String, _\r\n    ByVal Ort As String, ByVal Telefon As String, ByVal Telefax As String) As Int32\r\n    Dim sb As New System.Text.StringBuilder\r\n    sb.Append(\"INSERT INTO tblAdressen \")\r\n    sb.Append(\"(AnredeID, Vorname, Nachname, Strasse, PLZ, Ort, Telefon, Telefax) \")\r\n    sb.Append(\"VALUES (\")\r\n    If AnredeID = 0 Then\r\n        sb.Append(\"NULL, \")\r\n    Else\r\n        sb.Append(AnredeID.ToString() + \", \")\r\n    End If\r\n    sb.Append(Quote(Vorname) + \", \")\r\n    sb.Append(Quote(Nachname) + \", \")\r\n    sb.Append(Quote(Strasse) + \", \")\r\n    sb.Append(Quote(PLZ) + \", \")\r\n    sb.Append(Quote(Ort) + \", \")\r\n    sb.Append(Quote(Telefon) + \", \")\r\n    sb.Append(Quote(Telefax) + \") \")\r\n    Execute(sb)\r\nEnd Function<\/pre>\n<p><!--30percent--><\/p>\n<p><b>Quellcode 4<\/b><\/p>\n<p>Sie setzen ebenfalls SQL-Anweisungen zusammen, die dann per Execute-Methode zur Ausf&uuml;hrung gelangen (s. Quellcode 5 und 6).<\/p>\n<p>Die Execute-Methode erh&auml;lt ein auszuf&uuml;hrendes SQL-Statement als StringBuilder-Objekt &uuml;bergeben (s. Quellcode 7). F&uuml;r die Ausf&uuml;hrung des Objekts wird ein neues OleDbCommand-Objekt basierend auf der ge&ouml;ffneten DataLayer-Connection instanziert. Die ExecuteNonQuery-Methode f&uuml;hrt die Aktualisierungsabfrage aus.<\/p>\n<p>Die Quote-Funktion (s. Quellcode 8) ist bei der Bildung der SQL-Anweisungen erforderlich. Sie klammert einen String in Apostrophe. Falls der String bereits ein Apostroph enth&auml;lt, wird es durch zwei aufeinander folgende Apostrophe ersetzt.<\/p>\n<p>Die verschiedenen Methoden des Formulars teilen sich einige Variablen und eine Auflistung. Um diese Variablen zu definieren, sollten Sie unterhalb von<\/p>\n<pre>Public Function UpdateAdress(ByVal row As DataRow, ByVal AnredeID As Integer, _\r\n    ByVal Vorname As String, ByVal Nachname As String, ByVal Strasse As String, _\r\n    ByVal PLZ As String, ByVal Ort As String, ByVal Telefon As String, _\r\n    ByVal Telefax As String) As Int32\r\n    If (Not row Is Nothing) Then\r\n        Dim AdressID As Integer\r\n        AdressID = CInt(row.Item(\"AdressID\"))\r\n        Dim sb As New System.Text.StringBuilder\r\n        sb.Append(\"UPDATE tblAdressen SET  \")\r\n        If AnredeID = 0 Then\r\n            sb.Append(\"tblAdressen.AnredeID = NULL, \")\r\n        Else\r\n            sb.Append(\"tblAdressen.AnredeID = \" + AnredeID.ToString() + \", \")\r\n        End If\r\n        sb.Append(\"tblAdressen.Vorname = \" + Quote(Vorname) + \", \")\r\n        sb.Append(\"Nachname = \" + Quote(Nachname) + \", \")\r\n        sb.Append(\"Strasse = \" + Quote(Strasse) + \", \")\r\n        sb.Append(\"PLZ = \" + Quote(PLZ) + \", \")\r\n        sb.Append(\"Ort = \" + Quote(Ort) + \", \")\r\n        sb.Append(\"Telefon = \" + Quote(Telefon) + \", \")\r\n        sb.Append(\"Telefax = \" + Quote(Telefax) + \" \")\r\n        sb.Append(\"WHERE AdressID = \" + AdressID.ToString())\r\n        Execute(sb)\r\n    End If\r\nEnd Function<\/pre>\n<p><b>Quellcode 5<\/b><\/p>\n<pre>Public Sub DeleteAdress(ByVal row As DataRow)\r\n    If (Not row Is Nothing) Then\r\n        Dim AdressID As Integer\r\n        AdressID = CInt(row.Item(\"AdressID\"))\r\n        Dim sb As New System.Text.StringBuilder\r\n        sb.Append(\"DELETE FROM tblAdressen \")\r\n        sb.Append(\"WHERE AdressID = \" + AdressID.ToString())\r\n        Execute(sb)\r\n    End If\r\nEnd Sub<\/pre>\n<p><b>Quellcode 6<\/b><\/p>\n<pre>Public Class Adressen\r\nInherits System.Windows.Forms.Form<\/pre>\n<p>die folgenden Anweisungen einf&uuml;gen:<\/p>\n<pre>Private m_ConnectionString As String\r\nPrivate m_DataLayer As DataLayer\r\nPrivate m_Modus As Modus\r\nPrivate Enum Modus\r\nUpdate\r\nInsert\r\nNull\r\nEnd Enum<\/pre>\n<p>Die Variable m_ConnectionString speichert den ConnectionString; die Variable m_DataLayer bevorratet das DataLayer-Objekt, das von allen Methoden des Formulars verwendet werden kann. Die Variable m_Modus gibt Auskunft dar&uuml;ber, ob der Anwender gerade einen Datensatz anf&uuml;gt oder aktualisiert.<\/p>\n<pre>Private Sub Execute(ByVal sb As System.Text.StringBuilder)\r\n    Dim cmd As OleDbCommand\r\n    cmd = New OleDbCommand(sb.ToString, m_Cnn)\r\n    cmd.ExecuteNonQuery()\r\n    cmd.Dispose()\r\nEnd Sub<\/pre>\n<p><b>Quellcode 7<\/b><\/p>\n<pre>Private Function Quote(ByVal str As String)\r\n    Return \"''\" & Microsoft.VisualBasic.Replace(str, \"''\", \"''''\") & \"''\"\r\nEnd Function\r\nEnd Class<\/pre>\n<p><b>Quellcode 8<\/b><\/p>\n<pre>Private Sub FrmAdressenLoad(sender As System.Object, e As System.EventArgs)\r\n    m_ConnectionString = \"Provider=Microsoft.Jet.OLEDB.4.0;\" & _\r\n        \"Data Source=\" + System.Environment.CurrentDirectory + \"\\Adress00.mdb\"\r\n    m_DataLayer = New DataLayer(m_ConnectionString)\r\n    Me.cmbAnredeID.DataSource = m_DataLayer.GetAnreden()\r\n    Me.cmbAnredeID.ValueMember = \"AnredeID\"\r\n    Me.cmbAnredeID.DisplayMember = \"Anrede\"\r\n    SetListViewProperties()\r\n    AddHeader()\r\n    ShowData()\r\nEnd Sub<\/pre>\n<p><b>Quellcode 9<\/b><\/p>\n<h2>Die Load-Ereignisprozedur<\/h2>\n<p>Beim &ouml;ffnen des Formulars muss als Erstes das ListView-Steuerelement mit den Adressdaten gef&uuml;llt werden. Dazu sind folgende Schritte erforderlich:<\/p>\n<li>Die Datenherkunft des Kombinationsfeldes cmbAnredeID auf eine Liste der Anrede setzen.<\/li>\n<li>Dem ListView-Steuerelement muss eine Liste der &uuml;berschriften zugewiesen werden.<\/li>\n<li>Die Adressendaten m&uuml;ssen im ListView-Steuerelement angezeigt werden.<\/li>\n<p>Zur Durchf&uuml;hrung dieser Aufgaben wechseln Sie in die Entwurfsansicht des Formulars. Klicken Sie doppelt auf einen leeren Bereich des Formulars, damit SharpDevelop den Prozedurrumpf f&uuml;r das Load-Ereignis einf&uuml;gt.<\/p>\n<p>Um das Load-Ereignis zu implementieren, f&uuml;gen Sie den folgenden Programmcode in den Prozedurrumpf ein (s. Quellcode 9).<\/p>\n<p>Die erste Anweisung definiert den ConnectionString f&uuml;r den Zugriff auf die Adressdatenbank. Es handelt sich hierbei um die Beispieldatenbank Adress00.mdb, die schon in verschiedenen Beitr&auml;gen dieses Werks verwendet wurde.<\/p>\n<p>Das Programm erwartet die Datenbank in dem Verzeichnis, aus dem es gestartet wird. Anders gesagt: Sie sollten die Datenbank im gleichen Verzeichnis wie die EXE-Datei ablegen oder Sie passen den ConnectionString an das entsprechende Verzeichnis an.<\/p>\n<p>Der Variablen m_DataLayer wird eine Instanz der DataLayer-Klasse zugewiesen. Diese Instanz wird f&uuml;r alle Datenzugriffe des Formulars verwendet.<\/p>\n<pre>Private Sub SetListViewProperties()\r\n    With lstvAdressen\r\n        .View = View.Details\r\n        .LabelEdit = False\r\n        .AllowColumnReorder = True\r\n        .CheckBoxes = False\r\n        .FullRowSelect = True\r\n        .GridLines = True\r\n        .Sorting = SortOrder.None\r\n        .Activation = ItemActivation.Standard\r\n        .HideSelection = False\r\n        .MultiSelect = False\r\n        .HoverSelection = False\r\n    End With\r\nEnd Sub<\/pre>\n<p><b>Quellcode 10<\/b><\/p>\n<pre>Private Sub AddHeader()\r\n    With lstvAdressen.Columns\r\n        .Add(\"Anrede\", 50, HorizontalAlignment.Left)\r\n        .Add(\"Vorname\", 80, HorizontalAlignment.Left)\r\n        .Add(\"Nachname\", 80, HorizontalAlignment.Left)\r\n        .Add(\"Strasse\", 80, HorizontalAlignment.Left)\r\n        .Add(\"PLZ\", 50, HorizontalAlignment.Left)\r\n        .Add(\"Ort\", 80, HorizontalAlignment.Left)\r\n    End With\r\nEnd Sub<\/pre>\n<p><b>Quellcode 11<\/b><\/p>\n<p>Die Zuweisung von AnredeID an die Eigenschaft ValueMember des Steuerelements cmbAnredeID bewirkt, dass sich der Wert des Steuerelements durch den Wert des Feldes AnredeID definiert. Falls Sie also die Anrede Frau aus der Liste ausw&auml;hlen und Frau die AnredeID 5 hat, dann erh&auml;lt das Kombinationsfeld den Wert 5. Die Eigenschaft DisplayMember definiert den Namen der in der Liste Kombinationsfeldes anzuzeigenden Spalte. Sowohl der ValueMember als auch der DisplayMember m&uuml;ssen in der Datenherkunft des Kombinationsfeldes vorhanden sein. Die Datenherkunft selbst wird mit der DataSource-Eigenschaft an die Tabelle tblAnreden gebunden.<\/p>\n<h2>Eigenschaften des ListView-Steuerelements<\/h2>\n<p>Die Anzeige der Adressen erfolgt in einem ListView-Steuerelement. Steuerelemente dieses Typs k&ouml;nnen ihr Aussehen &auml;hnlich flexibel ver&auml;ndern wie die Dateiansicht im Windows Explorer. F&uuml;r die Anzeige der Adressen ist die Anzeige aller Spalten (View.Details) ohne Bilder oder Sonstiges erforderlich. Au&szlig;erdem muss ein Mausklick stets nur einen Datensatz markieren (FullRowSelect = True, MultiSelect = False).<\/p>\n<p>Die Prozedur SetListViewProperties setzt alle erforderlichen Eigenschaften zur Anzeige des ListView-Steuerelements (s. Quellcode 10).<\/p>\n<h2>Kopfzeile<\/h2>\n<p>Das ListView-Steuerelement soll nur ausgew&auml;hlte Spalten anzeigen. Bei der Definition des Steuerelements m&uuml;ssen Sie die Spalten einzeln per Add-Methode hinzuf&uuml;gen. Die Methode gibt Ihnen die M&ouml;glichkeit, f&uuml;r jede Spalte auch gleich eine &uuml;berschrift zu definieren. Die Methode AddHeader definiert alle &uuml;berschriften des ListView-Steuerelements (s. Quellcode 11).<\/p>\n<h2>Daten im ListView-Steuerelement anzeigen<\/h2>\n<p>Die ShowData-Prozedur &uuml;bernimmt die Anzeige der Adressen im ListView-Steuerelement (s. Quellcode 12). Die Prozedur bietet den Komfort, dass sie sich am Anfang die Nummer der im ListView-Steuerelement markierten Zeile merkt.<\/p>\n<p>Die GetAdressen-Methode des DataLayer-Objekts liest die Adressdaten aus der Access-Datenbank.<\/p>\n<pre>Private Sub ShowData()\r\n  Try\r\n    Dim iSelected As Integer\r\n    If lstvAdressen.Items.Count &gt; 0 Then\r\n      iSelected = 0\r\n      If lstvAdressen.SelectedItems.Count &gt; 0 _        Then\r\n        iSelected = lstvAdressen. _          SelectedItems.Item(0).Index\r\n      End If\r\n    End If\r\n    Dim tblAdressen As New DataTable\r\n    tblAdressen = m_DataLayer.GetAdressen()\r\n    Dim row As DataRow\r\n    Dim Item As ListViewItem\r\n    lstvAdressen.Items.Clear()\r\n    If tblAdressen.Rows.Count &gt; 0 Then\r\n  lstvAdressen.BeginUpdate()\r\n  Item = New ListViewItem\r\n  For Each row In tblAdressen.Rows\r\n        Item = lstvAdressen.Items. _          Add(row.Item(\"Anrede\").ToString())\r\n        With Item.SubItems\r\n          .Add(row.Item(\"Vorname\").ToString())\r\n          .Add(row.Item(\"Nachname\").ToString())\r\n          .Add(row.Item(\"Strasse\").ToString())\r\n          .Add(row.Item(\"PLZ\").ToString())\r\n          .Add(row.Item(\"Ort\").ToString())\r\n        End With\r\n        Item.Tag = row\r\n      Next\r\n      lstvAdressen.EndUpdate()\r\n    Else\r\n      m_Modus = Modus.Null\r\n    End If\r\n    If lstvAdressen.Items.Count &gt; 0 Then\r\n      iSelected = System.Math.Min(iSelected, _        lstvAdressen.Items.Count - 1)\r\n      lstvAdressen.Items(iSelected).Selected _        = True\r\n    End If\r\n  Catch ex As Exception\r\n    MessageBox.Show(ex.Message)\r\n  End Try\r\nEnd Sub<\/pre>\n<p><b>Quellcode 12<\/b><\/p>\n<p>Die Anzeige erfolgt in einer Schleife, die alle Zeilen des DataTable-Objekts durchl&auml;uft. F&uuml;r jeden Datensatz wird ein Item-Objekt im ListView-Steuerelement hinzugef&uuml;gt.<\/p>\n<p>Die Struktur des Steuerelements ist insofern ungew&ouml;hnlich, als dass es keine Spaltenauflistung im eigentlichen Sinne gibt. Es ist vielmehr so, dass mit Ausnahme der ersten Spalte f&uuml;r jede im Header definierte Spalte pro Item ein SubItem hinzugef&uuml;gt werden muss. Die mit AddHeader definierte Kopfzeile hat sechs Spalten. Pro Datensatz ist deshalb ein Item mit f&uuml;nf SubItems erforderlich. Die SubItems werden dem Item-Objekt einfach per Add-Methode hinzugef&uuml;gt.<\/p>\n<h3>Hinweis<\/h3>\n<p>Da es in der Einzelsatzansicht mehr Textfelder gibt, als das ListView-Steuerelement Spalten hat, ben&ouml;tigt das Programm einen Platz zum Speichern aller Datenfelder eines Datensatzes. Um diese Funktion m&ouml;glichst einfach und flexibel zu implementieren, wird das Row-Objekt ganz einfach in der Tag-Eigenschaft eines ListView-Items abgelegt. Damit kann der vollst&auml;ndige Datensatz jederzeit abgerufen werden. <\/p>\n<p>Am Ende der ShowData-Prozedur stellt das Programm fest, ob das ListView-Steuerelement Zeilen enth&auml;lt.<\/p>\n<p>Falls ja, kann es die vorher markierte Zeile wieder markieren.<\/p>\n<p><IMG height=\"351\" src=\"..\/fileadmin\/_temp_\/{8FB327D6-6197-4E11-9099-0FC6907FEBCF}\/pic003.png\" width=\"500\" border=\"0\"><\/p>\n<p><b><\/b><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3:  Dieses Formular kann die Adressen aus der Datenbank lesen und anzeigen.<\/span><\/b><\/p>\n<p><IMG height=\"393\" src=\"..\/fileadmin\/_temp_\/{8FB327D6-6197-4E11-9099-0FC6907FEBCF}\/pic004.png\" width=\"500\" border=\"0\"><\/p>\n<p><b><\/b><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4:  Mit einem Doppelklick auf ein Ereignis legen Sie eine neue Ereignisprozedur an.<\/span><\/b><\/p>\n<p>Das bisher erstellte Programm k&ouml;nnen Sie unter der Voraussetzung starten, dass Sie den Aufruf der ClearRecord-Prozedur auskommentieren. Mit dem Bet&auml;tigen der F5-Taste starten Sie das Programm und erhalten eine Anzeige wie in Bild 3.<\/p>\n<h2>Aktuellen Datensatz anzeigen<\/h2>\n<p>Das Programm kann die Adressen der zugrunde liegenden Tabelle bisher zwar in dem ListView-Steuerelement anzeigen. Doch was passiert, wenn Sie eine der Adressen anklicken Nichts!<\/p>\n<p>Um nun das zu erwartende Verhalten herbeizuf&uuml;hren, m&uuml;ssen Sie ein Ereignis abfangen, das bei einem Zeilenwechsel innerhalb des ListView-Steuerelements ausgel&ouml;st wird. <\/p>\n<p>Gehen Sie dazu wie folgt vor:<\/p>\n<li>Wechseln Sie in die Design-Ansicht des Formulars.<\/li>\n<li>Klicken Sie das ListView-Steuerelement mit der rechten Maustaste an und w&auml;hlen Sie den Befehl Eigenschaften aus dem Kontextmen&uuml;.<\/li>\n<li>Klicken Sie in der Symbolleiste des Eigenschaftenfensters auf das Symbol Ereignisse.<\/li>\n<li>Scrollen Sie herunter bis Sie wie in Bild 4 das Ereignis SelectedIndexChanged sehen.<\/li>\n<li>Klicken Sie doppelt auf den Eingabebereich f&uuml;r dieses Ereignis. (<\/li>\n<p>Dadurch legt SharpDevelop, eine neue Ereignisprozedur an und verkn&uuml;pft diese mit dem SelectedIndexChanged-Ereignis des ListView-Steuerelements.<\/p>\n<p>In den automatisch generierten Prozedurrumpf geben Sie die folgenden Anweisungen ein:<\/p>\n<pre>If Me.lstvAdressen.SelectedItems.Count _    &gt; 0 Then\r\n    m_Modus = Modus.Update\r\n    ShowRecord(GetSelectedRow)\r\nElse\r\n    m_Modus = Modus.Null\r\n    ClearRecord()\r\nEnd If\r\nPrivate Sub ShowRecord(ByVal row As DataRow)\r\n    If (Not row Is Nothing) Then\r\n        If row.Item(\"AnredeID\").ToString = \"\" Then\r\n            Me.cmbAnredeID.SelectedValue = 0\r\n        Else\r\n            Me.cmbAnredeID.SelectedValue = _                row.Item(\"AnredeID\").ToString()\r\n        End If\r\n    Me.txtVorname.Text = row.Item(\"Vorname\").ToString()\r\n    Me.txtNachname.Text = _      row.Item(\"Nachname\").ToString()\r\n    Me.txtStrasse.Text = row.Item(\"Strasse\").ToString()\r\n    Me.txtPLZ.Text = row.Item(\"PLZ\").ToString()\r\n    Me.txtOrt.Text = row.Item(\"Ort\").ToString()\r\n    Me.txtTelefon.Text = row.Item(\"Telefon\").ToString()\r\n    Me.txtTelefax.Text = row.Item(\"Telefax\").ToString()\r\n  End If\r\n  ShowButtons()\r\nEnd Sub<\/pre>\n<p><b>Quellcode 13<\/b><\/p>\n<pre>Private Function GetSelectedRow() As DataRow\r\n  Dim row As DataRow\r\n  If lstvAdressen.SelectedItems.Count &gt; 0 Then\r\n    row = lstvAdressen.SelectedItems.Item(0).Tag\r\n  End If\r\n  Return row\r\nEnd Function<\/pre>\n<p><b>Quellcode 14<\/b><\/p>\n<pre>Private Sub ClearRecord()\r\n  Me.cmbAnredeID.SelectedItem = Nothing\r\n  Me.txtVorname.Text = \"\"\r\n  Me.txtNachname.Text = \"\"\r\n  Me.txtStrasse.Text = \"\"\r\n  Me.txtPLZ.Text = \"\"\r\n  Me.txtOrt.Text = \"\"\r\n  Me.txtTelefon.Text = \"\"\r\n  Me.txtTelefax.Text = \"\"\r\n  ShowButtons()\r\nEnd Sub<\/pre>\n<p><b>Quellcode 15<\/b><\/p>\n<p>Diese Prozedur wird immer dann ausgef&uuml;hrt, wenn im ListView-Steuerelement eine andere Zeile selektiert wird. Dies kann durch Anklicken mit der Maus, durch die Tastatur oder durch das Programm erfolgen.<\/p>\n<p>Die Ereignisprozedur pr&uuml;ft, ob im ListView-Steuerelement eine Zeile selektiert ist. Falls ja, &auml;ndert die Prozedur den Formularmodus auf Update und ruft die Prozedur ShowRecord mit dem aktuell selektierten Datensatz als Parameter auf. Die Prozedur ShowRecord (s. Quellcode 13) zeigt die Einzelansicht des Datensatzes an.<\/p>\n<p>Die ShowRecord-Funktion ben&ouml;tigt mehr Informationen als in den Spalten des ListView-Steuerelements angezeigt werden. Um diesem Fall vorzubeugen, wurde weiter oben das gesamte DataRow-Objekt in der Tag-Eigenschaft eines jeden Items hinterlegt. Die GetSelectedRow-Funktion ermittelt genau dieses DataRow-Objekt der aktuell im ListView-Steuerelement markierten Zeile und gibt es als Funktionswert zur&uuml;ck (s. Quellcode 14).<\/p>\n<p>Besonders interessant ist die Zuweisung row = &#8230; In dieser Zeile wird das aus der Tag-Eigenschaft ausgelesene Objekt vom Typ Object implizit in ein DataRow-Objekt umgewandelt. Falls Sie das Programm mit Option Strict On kompilieren lassen, erhalten Sie an dieser Stelle eine Fehlermeldung. In diesem Fall m&uuml;ssen Sie die Typumwandlung explizit wie folgt veranlassen:<\/p>\n<pre>row = DirectCast( _    lstvAdressen. _    SelectedItems. _    Item(0).Tag, DataRow)<\/pre>\n<h3>Leere Anzeige<\/h3>\n<p>Falls kein Datensatz im ListView-Steuerelement selektiert ist, &auml;ndert die Ereignisprozedur den Formularstatus auf Null, und ruft die Prozedur ClearRecord auf (s. Quellcode 15). Die Prozedur ClearRecord leert den Anzeigebereich f&uuml;r die Einzelsatzdarstellung.<\/p>\n<p>Beide Prozeduren, also ShowRecord und ClearRecord rufen am Ende die Prozedur ShowButtons (s. Quellcode 16) auf. Diese Prozedur blendet abh&auml;ngig vom aktuellen Formularmodus die Befehlsschaltfl&auml;chen zur Anlage, zur Bearbeitung und zum L&ouml;schen von Adressen ein und aus.<\/p>\n<pre>Private Sub ShowButtons()\r\n  Select Case m_Modus\r\n    Case Modus.Insert\r\n      Me.btnSpeichern.Text = \"&Anf&uuml;gen\"\r\n      Me.btnSpeichern.Visible = True\r\n      Me.btnNeueAdresse.Visible = False\r\n      Me.btnL&ouml;schen.Visible = False\r\n    Case Modus.Update\r\n      Me.btnSpeichern.Text = _        \"&Speichern\"\r\n      Me.btnSpeichern.Visible = True\r\n      Me.btnNeueAdresse.Visible = True\r\n      Me.btnL&ouml;schen.Visible = True\r\n    Case Modus.Null\r\n      Me.btnSpeichern.Visible = False\r\n      Me.btnNeueAdresse.Visible = True\r\n      Me.btnL&ouml;schen.Visible = False\r\n  End Select\r\nEnd Sub<\/pre>\n<p><b>Quellcode 16<\/b><\/p>\n<p>Wenn Sie das Programm jetzt starten, dann erhalten Sie nat&uuml;rlich Kompilierfehler. Der Grund besteht darin, dass Sie auf Schaltfl&auml;chen Bezug nehmen, die noch gar nicht angelegt sind. Wenn Sie die entsprechenden Programmzeilen auskommentieren, dann startet das Programm wie in Bild 3. Das Einlesen und Anzeigen von Adressen funktioniert bereits. Derzeit fehlen aber noch die Schaltfl&auml;chen zum Einf&uuml;gen, &auml;ndern und L&ouml;schen von Datens&auml;tzen.<\/p>\n<h2>Schaltfl&auml;chen anlegen<\/h2>\n<li>Zur Anlage der erforderlichen Schaltfl&auml;chen sollten Sie in die Entwurfsansicht wechseln.<\/li>\n<li>F&uuml;gen Sie mit Hilfe der Toolbox die vier Button-Steuerelemente btnNeueAdresse, btnSpeichern, btnL&ouml;schen und btnBeenden ein.<\/li>\n<h2>Adresse anlegen<\/h2>\n<p>Um einem Button eine neue Ereignisprozedur zuzuweisen, brauchen Sie ihn nur doppelt anzuklicken. SharpDevelop f&uuml;gt dann automatisch einen Prozedurrumpf ein, den Sie allerdings noch mit Inhalt f&uuml;llen m&uuml;ssen. Die so entstandene Prozedur zur Anlage einer neuen Adresse sieht folgenderma&szlig;en aus:<\/p>\n<pre>Private Sub BtnNeueAdresseClick(sender _    As System.Object, _    e As System.EventArgs)\r\n    m_Modus = Modus.Insert\r\n    ClearRecord()\r\nEnd Sub<\/pre>\n<p>In dem Bereich Windows Forms Designer generated code f&uuml;gt SharpDevelop automatisch die folgende Programmzeile ein:<\/p>\n<pre>AddHandler Me.btnNeueAdresse.Click,\r\nAddressOf Me.BtnNeueAdresseClick<\/pre>\n<p>Diese Programmzeile verkn&uuml;pft das Click-Ereignis der Schaltfl&auml;che mit der Ereignisprozedur. Die folgende Anweisung &auml;ndert den Modus des Formulars auf Insert:<\/p>\n<pre>m_Modus = Modus.Insert<\/pre>\n<p>In diesem Modus soll der Anwender Gelegenheit haben, die Daten f&uuml;r einen neu hinzuzuf&uuml;genden Datensatz einzugeben. Damit ihn nichts dabei st&ouml;rt, leert ein Aufruf der Prozedur ClearRecord den Anzeigebereich f&uuml;r den Datensatz und ruft au&szlig;erdem die Prozedur ShowButtons auf.<\/p>\n<h2>Datensatz speichern<\/h2>\n<p>Die mit dem Button-Steuerelement btnSpeichern verkn&uuml;pfte Ereignisprozedur soll einen Datensatz speichern. Dabei kann es sich um die Anlage eines neuen Datensatzes oder um die Aktualisierung eines bestehenden Datensatzes handeln. Je nachdem wird entweder die AddAdresse oder die UpdateAdresse-Methode der DataLayer-Klasse aufgerufen (s. Quellcode 17).<\/p>\n<pre>Private Sub BtnSpeichernClick(sender As System.Object, e As System.EventArgs)\r\n    If m_Modus = Modus.Insert Then\r\n        m_DataLayer.AddAdresse(Me.cmbAnredeID.SelectedValue, Me.txtVorname.Text, _\r\n            Me.txtNachname.Text, Me.txtStrasse.Text, Me.txtPLZ.Text, Me.txtOrt.Text, _\r\n            Me.txtTelefon.Text, Me.txtTelefax.Text)\r\n    Else\r\n        m_DataLayer.UpdateAresse(GetSelectedRow(), Me.cmbAnredeID.SelectedValue, _\r\n            Me.txtVorname.Text, Me.txtNachname.Text, Me.txtStrasse.Text, _\r\n            Me.txtPLZ.Text, Me.txtOrt.Text, Me.txtTelefon.Text, Me.txtTelefax.Text)\r\n    End If\r\n    m_Modus = Modus.Update\r\n    ShowData()\r\nEnd Sub<\/pre>\n<p><b>Quellcode 17<\/b><\/p>\n<p>Falls die Speichern-Routine einen bestehenden Datensatz aktualisieren soll, ben&ouml;tigt sie den Prim&auml;rschl&uuml;ssel dieses Datensatzes. Dieser befindet sich aber nur in der Datenquelle des ListView-Steuerelements. Um ihn benutzen zu k&ouml;nnen, muss das DataRow-Objekt aus der Tag-Eigenschaft des aktuellen im ListView markierten Items ausgelesen werden. Genau diese Aufgabe &uuml;bernimmt die GetSelectedRow-Prozedur.<\/p>\n<p>Am Ende des Speicherns wird in jedem Fall die ShowData-Prozedur aufgerufen. Dieser Prozeduraufruf garantiert, dass die im ListView-Steuerelement angezeigten Daten mit den Daten der zugrunde liegenden Tabelle synchron sind.<\/p>\n<h2>Datensatz l&ouml;schen<\/h2>\n<p>Das L&ouml;schen eines Datensatzes erfordert nur noch wenig Programmcode. Zur Anlage der Ereignisprozedur klicken Sie einfach doppelt auf die Schaltfl&auml;che L&ouml;schen. Geben Sie dann die folgenden Anweisungen ein:<\/p>\n<pre>m_DataLayer. _    DeleteAresse(GetSelectedRow())\r\nm_Modus = Modus.Update\r\nShowData()<\/pre>\n<p>Die L&ouml;schroutine ermittelt den aktuell markierten Datensatz und &uuml;bergibt diesen als Parameter an den DataLayer. Dort sorgt die DeleteAdress-Methode f&uuml;r das L&ouml;schen des Datensatzes. An der Oberfl&auml;che muss nur noch der Formularmodus auf Update gesetzt werden. Die Aktualisierung der Anzeige erledigt die ShowData-Prozedur.<\/p>\n<h2>Das Programm beenden<\/h2>\n<p>Die letzte noch fehlende Ereignisprozedur soll das Programm beenden. Um sie einzugeben, f&uuml;hren Sie einen Doppelklick auf die Beenden-Schaltfl&auml;che durch. Geben Sie dann die folgenden Programmzeilen ein:<\/p>\n<pre>m_DataLayer.Dispose()\r\nMe.Close()<\/pre>\n<p>Der Aufruf der Dispose-Methode schlie&szlig;t das DataLayer-Objekt. Dies f&uuml;hrt automatisch auch zum Schlie&szlig;en der offenen Connection. Die Anweisung Me.Close() schlie&szlig;t das aktuelle Formular und beendet damit die Anwendung.<\/p>\n<p>Im vorliegenden Beitrag haben Sie erfahren, wie Sie mit .NET Windows-Formulare f&uuml;r den Zugriff auf in Datenbanken gespeicherte Daten erm&ouml;glichen. Das vorgestellte Formular lie&szlig;e sich leicht um weitere Steuerelementtypen erweitern. Funktionell w&uuml;rde das Hinzuf&uuml;gen einer Suchfunktion Sinn machen und auch die Anzeige von per 1:n-Beziehung verkn&uuml;pften Daten l&auml;sst sich hierauf aufbauen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im ersten Teil dieses Beitrags haben Sie die Adressen aus einer Access-Datenbank in ein DataGrid-Steuerelement geladen. In diesem zweiten Teil steigen Sie tiefer in die Programmierung ein und erfahren, wie Sie Adressen aus einem Listensteuerelement ausw&auml;hlen und komfortabel in der Einzel-ansicht bearbeiten k&ouml;nnen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[44000017,66012005,662005,44000027],"tags":[],"class_list":["post-55000265","post","type-post","status-publish","format-standard","hentry","category-NET","category-66012005","category-662005","category-Loesungen"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Adressverwaltung mit .NET, Teil 2 - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Adressverwaltung mit .NET, Teil 2\" \/>\n<meta property=\"og:description\" content=\"Im ersten Teil dieses Beitrags haben Sie die Adressen aus einer Access-Datenbank in ein DataGrid-Steuerelement geladen. In diesem zweiten Teil steigen Sie tiefer in die Programmierung ein und erfahren, wie Sie Adressen aus einem Listensteuerelement ausw&auml;hlen und komfortabel in der Einzel-ansicht bearbeiten k&ouml;nnen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-06T15:17:56+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg08.met.vgwort.de\/na\/3af6b630ea33483fa9969e6e1e4dec30\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"22\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Adressverwaltung mit .NET, Teil 2\",\"datePublished\":\"2020-05-06T15:17:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/\"},\"wordCount\":3242,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/3af6b630ea33483fa9969e6e1e4dec30\",\"articleSection\":[\".NET\",\"1\\\/2005\",\"2005\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/\",\"name\":\"Adressverwaltung mit .NET, Teil 2 - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/3af6b630ea33483fa9969e6e1e4dec30\",\"datePublished\":\"2020-05-06T15:17:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/3af6b630ea33483fa9969e6e1e4dec30\",\"contentUrl\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/3af6b630ea33483fa9969e6e1e4dec30\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Adressverwaltung_mit_NET_Teil_2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Adressverwaltung mit .NET, Teil 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Adressverwaltung mit .NET, Teil 2 - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/","og_locale":"de_DE","og_type":"article","og_title":"Adressverwaltung mit .NET, Teil 2","og_description":"Im ersten Teil dieses Beitrags haben Sie die Adressen aus einer Access-Datenbank in ein DataGrid-Steuerelement geladen. In diesem zweiten Teil steigen Sie tiefer in die Programmierung ein und erfahren, wie Sie Adressen aus einem Listensteuerelement ausw&auml;hlen und komfortabel in der Einzel-ansicht bearbeiten k&ouml;nnen.","og_url":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-06T15:17:56+00:00","og_image":[{"url":"http:\/\/vg08.met.vgwort.de\/na\/3af6b630ea33483fa9969e6e1e4dec30","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"22\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Adressverwaltung mit .NET, Teil 2","datePublished":"2020-05-06T15:17:56+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/"},"wordCount":3242,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/#primaryimage"},"thumbnailUrl":"http:\/\/vg08.met.vgwort.de\/na\/3af6b630ea33483fa9969e6e1e4dec30","articleSection":[".NET","1\/2005","2005","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/","url":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/","name":"Adressverwaltung mit .NET, Teil 2 - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/#primaryimage"},"thumbnailUrl":"http:\/\/vg08.met.vgwort.de\/na\/3af6b630ea33483fa9969e6e1e4dec30","datePublished":"2020-05-06T15:17:56+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/#primaryimage","url":"http:\/\/vg08.met.vgwort.de\/na\/3af6b630ea33483fa9969e6e1e4dec30","contentUrl":"http:\/\/vg08.met.vgwort.de\/na\/3af6b630ea33483fa9969e6e1e4dec30"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Adressverwaltung_mit_NET_Teil_2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Adressverwaltung mit .NET, Teil 2"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000265","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55000265"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000265\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000265"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000265"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000265"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}