{"id":55000175,"date":"2019-04-01T00:00:00","date_gmt":"2020-03-27T19:37:21","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=175"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Validieren_mit_VB_und_EDM","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Validieren_mit_VB_und_EDM\/","title":{"rendered":"Validieren mit VB und EDM"},"content":{"rendered":"<p><b>Im Artikel EDM: Validieren von Entit&auml;ten mit IDataErrorInfo haben wir bereits erl&auml;utert, wie Sie einer auf dem Entity Framework basierenden Anwendung eine Validierung hinzuf&uuml;gen k&ouml;nnen. Im vorliegenden Artikel schauen wir uns an, wie Sie die Validierung nicht unter C#, sondern unter VB realisieren und welche &Auml;nderungen in den Methoden zum Migrieren einer Access-Anwendung nach WPF\/EDM notwendig sind, um die Validierung vorzubereiten oder gegebenenfalls auch direkt umzusetzen.<\/b><\/p>\n<p>F&uuml;r die Programmierung einer Validierung in den Klassen des Entity Data Models und der mit WPF definierten Benutzeroberfl&auml;che sind einige Schritte auf den verschiedenen Ebenen erforderlich. Der erste ist, die Entit&auml;tsklassen mit der Implementierung der Schnittstelle <b>IDataErrorInfo <\/b>zu versehen, die zweite die Definition der Anzeige der Validierungsmeldungen in der Benutzeroberfl&auml;che &#8211; und das geschieht durch entsprechende WPF-Elemente.<\/p>\n<h2>IDataErrorInfo &#8211; wo implementieren<\/h2>\n<p>Im oben genannten Artikel haben wir unter C# die Schnittstelle <b>IDataErrorInfo<\/b> f&uuml;r partielle Klassen implementiert. Das bedeutet, dass wir zwei gleichnamige Klassen programmiert haben, wobei wir in der einen die Definition der Properties und in der anderen die Implementierung der Schnittstelle <b>IDataErrorInfo <\/b>eingef&uuml;gt haben. Warum haben wir das dort so gemacht Weil wir den Code f&uuml;r die Entit&auml;tsklassen aus dem Datenmodell der Datenbank generiert haben, was bedeutet, dass wir bei &Auml;nderungen des Datenmodells auch die Entit&auml;tsklassen neu generieren mussten. Wenn wir dann die Implementierung der Schnittstelle <b>IDataErrorInfo <\/b>in der automatisch generierten Entit&auml;tsklasse programmiert h&auml;tte, w&auml;re diese bei jeder Aktualisierung wieder &uuml;berschrieben worden. Deshalb haben wir diese Definition direkt in eigenen, partiellen Klassen programmiert. Partielle Klasse bedeutet dabei, dass wir einfach eine weitere Klasse gleichen Namens mit dem Schl&uuml;sselwort <b>Partial <\/b>erstellt und dort die Elemente f&uuml;r die Implementierung der Schnittstelle hineingeschrieben haben. Die Klassenbezeichnungen der per Generator erzeugten Entit&auml;tsklassen wurden dabei praktischerweise bereits mit dem Schl&uuml;sselwort Partial ausgezeichnet &#8211; was keinen Nachteil bringt, auch wenn es keine weiteren partiellen Klassen mehr gibt.<\/p>\n<p>Nun verwenden wir in der aktuell in diesem Magazin beschriebenen Vorgehensweise eine Access-Datenbank als Vorlage f&uuml;r die Erstellung eines Entity Data Models und auch f&uuml;r die Erstellung von Fenstern auf Basis der Formulare der Access-Datenbank. Wir k&ouml;nnten also theoretisch auch gleich die Implementierung der Schnittstelle <b>IDataErrorInfo <\/b>in die Entit&auml;tsklassen schreiben &#8211; und hier direkt die im Datenmodell festgelegten Restriktionen wie keine Nullwerte et cetera eintragen. Allerdings kann es auch hier sein, dass Sie die Implementierung der Schnittstelle <b>IDataErrorInfo<\/b> selbst anpassen wollen. Also werden wir auch hier mit partiellen Klassen arbeiten und per Parameter beim Erstellen des Entity Data Models auf Basis der Tabellen der Access-Datenbank die M&ouml;glichkeit bieten, entweder nur das Entity Data Model zu erstellen oder auch noch die partiellen Klassen mit den Validierungsfunktionen neu zu generieren. Zun&auml;chst schauen wir uns allerdings an, wie die partiellen Klassen unter VB &uuml;berhaupt aussehen sollen.<\/p>\n<h2>Partielle Klasse mit IDataErrorInfo erstellen<\/h2>\n<p>Das Anlegen der zus&auml;tzlichen partiellen Klasse etwa f&uuml;r die Klasse <b>Kunde <\/b>erfordert zwei Schritte. Als Erstes f&uuml;gen wir der eigentlichen Klasse das Schl&uuml;sselwort <b>Partial <\/b>als erstes Schl&uuml;sselwort noch vor <b>Public <\/b>hinzu:<\/p>\n<pre>&lt;Table(\"Kunden\")&gt;\r\nPartial Public Class Kunde\r\n     ...\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>Danach k&ouml;nnen wir die zweite partielle Klasse erstellen:<\/p>\n<pre>Partial Public Class Kunde\r\n     ...\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>F&uuml;r diese Klasse wollen wir nun die Schnittstelle <b>IDataErrorInfo <\/b>implementieren. Dazu ben&ouml;tigen wir zun&auml;chst die Bibliothek System.<b>ComponentModel<\/b>, die wir per <b>Imports<\/b>-Anweisung hinzuf&uuml;gen:<\/p>\n<pre>Imports System.ComponentModel<\/pre>\n<p>Danach f&uuml;gen Sie in der Zeile unter der Klassendefinition die Anweisung zur Implementierung der Schnittstelle hinzu:<\/p>\n<pre>Partial Public Class Kunde\r\n     Implements IDataErrorInfo<\/pre>\n<p>    &#8230;<\/p>\n<p>Wenn Sie mit der rechten Maustaste auf <b>IDataErrInfo <\/b>klicken, erscheint der Kontextmen&uuml;-Eintrag <b>Schnellaktionen und Refactorings&#8230;<\/b>, den Sie anklicken und danach den nun erscheinenden Befehl <b>Schnittstelle implementieren <\/b>anklicken (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_175_001.png\" alt=\"Automatisches Implementieren der Schnittstelle\" width=\"700\" height=\"345,5077\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Automatisches Implementieren der Schnittstelle<\/span><\/b><\/p>\n<p>Das f&uuml;llt die Klasse mit den beiden Properties <b>Item <\/b>und <b>[Error]<\/b>:<\/p>\n<pre>Partial Public Class Kunde\r\n     Implements IDataErrorInfo\r\n     Default Public ReadOnly Property Item(columnName<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span> Implements IDataErrorInfo.Item\r\n         Get\r\n             Throw <span style=\"color:blue;\">New<\/span> NotImplementedException()\r\n         End Get\r\n     End Property\r\n     <span style=\"color:blue;\">Public <\/span>ReadOnly Property [Error]<span style=\"color:blue;\"> As String<\/span> Implements IDataErrorInfo.Error\r\n         Get\r\n             Throw <span style=\"color:blue;\">New<\/span> NotImplementedException()\r\n         End Get\r\n     End Property\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>Uns interessiert dabei speziell die <b>Property <\/b>namens <b>Item<\/b>. Diese liefert mit dem Parameter <b>columnName <\/b>den Namen des Feldes, f&uuml;r das eine Validierung durchgef&uuml;hrt werden soll. Um eine Validierung f&uuml;r das Feld <b>Vorname <\/b>durchzuf&uuml;hren, die pr&uuml;fen soll, ob das Feld <b>Vorname <\/b>leer ist, f&uuml;gen Sie die folgende <b>Select Case<\/b>-Bedingung mit dem <b>Case<\/b>-Zweig f&uuml;r den Feldnamen <b>Vorname <\/b>hinzu. Die Pr&uuml;fung stellt mit der Methode <b>IsNullOrEmpty <\/b>fest, ob <b>Vorname <\/b>leer ist. In diesem Fall wird der R&uuml;ckgabeparameter <b>strErrorMessage <\/b>mit einer entsprechenden Fehlermeldung gef&uuml;llt:<\/p>\n<pre>Default Public ReadOnly Property Item(columnName<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span> Implements IDataErrorInfo.Item\r\n     Get\r\n         <span style=\"color:blue;\">Dim <\/span>strErrorMessage<span style=\"color:blue;\"> As String<\/span> = \"\"\r\n         Select Case columnName\r\n             <span style=\"color:blue;\">Case <\/span>\"Vorname\"\r\n                 <span style=\"color:blue;\">If <\/span>(String.IsNullOrEmpty(Vorname))<span style=\"color:blue;\"> Then<\/span>\r\n                     strErrorMessage = \"Bitte geben Sie einen Vornamen ein.\"\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n         Return strErrorMessage\r\n     End Get\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Nun stellt sich nur noch die Frage, wodurch diese Methode aufgerufen wird und wie wir die Fehlermeldung aus <b>strErrorMessage <\/b>verarbeiten.<\/p>\n<h2>Ausl&ouml;sen der Validierung<\/h2>\n<p>Dass f&uuml;r das Feld <b>Vorname <\/b>eine Validierung ausgel&ouml;st wird, legen wir in der Definition des an dieses Feld gebundenen Steuerelements fest, in diesem Fall des Textfeldes <b>txtVorname<\/b>. Hier erweitern wir den Inhalt der Bindung f&uuml;r das Attribut <b>Text <\/b>um <b>ValidatesOnDataErrors=True<\/b>:<\/p>\n<pre>&lt;TextBox x:Name=\"txtVorname\" Text=\"{Binding Kunde.Vorname, ValidatesOnDataErrors=True}\" Height=\"21\" Margin=\"118,58,0,0\" Width=\"221\"\/&gt;<\/pre>\n<p>Damit allein wird nun bereits die Validierung ausgel&ouml;st, das hei&szlig;t, wenn das Feld <b>Vorname <\/b>angezeigt wird, ruft dies auch die Methode <b>Item <\/b>der Implementierung von <b>IDataErrorInfo <\/b>auf. Das Ergebnis ist allerdings noch keine Anzeige der Meldung, sondern zun&auml;chst nur das rote Einrahmen des Feldes, das nicht erfolgreich validiert werden konnte (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_175_002.png\" alt=\"Die Validierung funktioniert bereits.\" width=\"349,7625\" height=\"338,77\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Die Validierung funktioniert bereits.<\/span><\/b><\/p>\n<p>Wir wollen allerdings noch konkretere Hinweise auf den Grund f&uuml;r die farbige Markierung liefern, damit der Benutzer wei&szlig;, was zu tun ist. Also verwenden wir den Setter, den wir auch schon im oben genannten Artikel genutzt haben, um die Fehlermeldung an entsprechender Stelle unterzubringen. Dazu erweitern wir den Code f&uuml;r das <b>Style<\/b>-Element in der <b>.xaml<\/b>-Datei wie folgt:<\/p>\n<pre>&lt;Style TargetType=\"{x:Type TextBox}\"&gt;\r\n     ...\r\n     &lt;Setter Property=\"Validation.ErrorTemplate\"&gt;\r\n         &lt;Setter.Value&gt;\r\n             &lt;ControlTemplate&gt;\r\n                 &lt;DockPanel&gt;\r\n                     &lt;Border Background=\"Red\" DockPanel.Dock=\"right\" Margin=\"5,0,0,0\" Width=\"20\" Height=\"20\"                             CornerRadius=\"10\" ToolTip=\"{Binding ElementName=customAdorner,                             Path=AdornedElement.(Validation.Errors)[0].ErrorContent}\"&gt;\r\n                         &lt;TextBlock Text=\"!\" VerticalAlignment=\"center\" HorizontalAlignment=\"center\"                            FontWeight=\"Bold\" Foreground=\"white\" \/&gt;\r\n                     &lt;\/Border&gt;\r\n                     &lt;AdornedElementPlaceholder Name=\"customAdorner\" VerticalAlignment=\"Center\" &gt;\r\n                         &lt;Border BorderBrush=\"red\" BorderThickness=\"1\" \/&gt;\r\n                     &lt;\/AdornedElementPlaceholder&gt;\r\n                 &lt;\/DockPanel&gt;\r\n             &lt;\/ControlTemplate&gt;\r\n         &lt;\/Setter.Value&gt;\r\n     &lt;\/Setter&gt;\r\n&lt;\/Style&gt;<\/pre>\n<p>Danach erscheint die Meldung, die wir f&uuml;r das Feld <b>Vorname<\/b> definiert haben, wie in Bild 3.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_175_003.png\" alt=\"Validierung mit Hinweismeldung\" width=\"349,7625\" height=\"318,0507\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Validierung mit Hinweismeldung<\/span><\/b><\/p>\n<h2>Validierung von Kombinationsfeldern<\/h2>\n<p>F&uuml;r die Validierung des Kombinationsfeldes <b>Anrede <\/b>f&uuml;gen Sie in der <b>.xaml<\/b>-Datei f&uuml;r die Definition des <b>Style<\/b>-Elements f&uuml;r den Typ <b>ComboBox <\/b>genau die gleiche Property namens <b>Validation.ErrorTemplate <\/b>wie f&uuml;r den Typ <b>TextBox <\/b>hinzu:<\/p>\n<pre>&lt;Style TargetType=\"{x:Type ComboBox}\"&gt;\r\n     ...\r\n     &lt;Setter Property=\"Validation.ErrorTemplate\"&gt;\r\n     ...\r\n     &lt;\/Setter&gt;\r\n&lt;\/Style&gt;<\/pre>\n<p>Au&szlig;erdem passen Sie in der Definition des <b>ComboBox<\/b>-Elements das Attribut <b>SelectedItem <\/b>so an, dass die Bindung mit der Option <b>ValidatesOnDataErrors=True <\/b>erfolgt:<\/p>\n<pre>&lt;ComboBox x:Name=\"cboAnredeID\" Padding=\"0\" Height=\"21\" Margin=\"118,111,0,0\" Width=\"78\"\r\n     ItemsSource = \"{Binding Anreden}\"\r\n     SelectedItem = \"{Binding Kunde.Anrede, ValidatesOnDataErrors=True}\"\r\n     ...\r\n&lt;\/ComboBox&gt;<\/pre>\n<p>Schlie&szlig;lich erweitern wir die Implementierung der Schnittstelle <b>IDataErrorInfo <\/b>noch um einen entsprechenden <b>Case<\/b>-Zweig. Hier verwenden wir allerdings die <b>IsNothing<\/b>-Funktion, um zu pr&uuml;fen, ob f&uuml;r die Eigenschaft <b>Anrede <\/b>eines der Elemente der Auflistung <b>Anreden <\/b>zugewiesen wurde:<\/p>\n<pre>Default Public ReadOnly Property Item(columnName<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span> Implements IDataErrorInfo.Item\r\n     Get\r\n         <span style=\"color:blue;\">Dim <\/span>strErrorMessage<span style=\"color:blue;\"> As String<\/span> = \"\"\r\n         Select Case columnName\r\n             ...\r\n             <span style=\"color:blue;\">Case <\/span>\"Anrede\"\r\n                 <span style=\"color:blue;\">If <\/span>(IsNothing(Anrede))<span style=\"color:blue;\"> Then<\/span>\r\n                     strErrorMessage = \"Bitte w&auml;hlen Sie eine Anrede aus.\"\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n         Return strErrorMessage\r\n     End Get\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<h2>Verlassen des Datensatzes ohne erfolgreiche Validierung unterbinden<\/h2>\n<p>Nun m&uuml;ssen wir noch sicherstellen, dass der Benutzer den Datensatz nicht verlassen kann, ohne dass alle erforderlichen Daten eingegeben wurden. Dazu haben wir im oben genannten Artikel eine Technik kennengelernt, die auf den Ergebnissen unserer Validierung aufbaut und davon abh&auml;ngig Steuer-elemente aktiviert oder deaktiviert. Dabei haben wir f&uuml;r die betroffene Schaltfl&auml;che <b>DataTrigger<\/b>-Element als <b>Style<\/b>-Elemente festgelegt und f&uuml;r jeden Trigger eine Bedingung formuliert, unter der eine bestimmte Eigenschaft auf einen Wert eingestellt werden soll &#8211; in diesem Fall etwa der Wert der Validierung eines oder mehrerer gebundener Steuer-elemente und damit verbunden die Eigenschaft <b>IsEnabled <\/b>der zu deaktivierenden Schaltfl&auml;che.<\/p>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Visual Basic Entwickler<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/363\/visual-basic-entwickler-jahresabonnement?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 200 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000175\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/data\/wp\/v2\/posts\/55000175?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000175\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"dbce743e9d\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Artikel EDM: Validieren von Entit&auml;ten mit IDataErrorInfo haben wir bereits erl&auml;utert, wie Sie einer auf dem Entity Framework basierenden Anwendung eine Validierung hinzuf&uuml;gen k&ouml;nnen. Im vorliegenden Artikel schauen wir uns an, wie Sie die Validierung nicht unter C#, sondern unter VB realisieren und welche &Auml;nderungen in den Methoden zum Migrieren einer Access-Anwendung nach WPF\/EDM notwendig sind, um die Validierung vorzubereiten oder gegebenenfalls auch direkt umzusetzen.<\/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":[66022019,662019,44000021,44000016],"tags":[],"yst_prominent_words":[],"class_list":["post-55000175","post","type-post","status-publish","format-standard","hentry","category-66022019","category-662019","category-Entity_Framework","category-VBGrundlagen"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000175","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000175"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000175\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000175"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}