{"id":55000065,"date":"2016-12-01T00:00:00","date_gmt":"2020-03-27T19:23:39","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=65"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Events_in_der_Praxis","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Events_in_der_Praxis\/","title":{"rendered":"Events in der Praxis"},"content":{"rendered":"<p><b>Im Artikel &#8220;Von VBA zu C#: Objekt-Ereignisse&#8221; haben wir bereits die Grundlagen zur Programmierung und Implementierung benutzerdefinierter Ereignisse gelegt. Dies wollen wir nun ausbauen, indem wir uns zwei praktische Beispiele ansehen. Dabei wollen wir von einem Hauptfenster aus verschiedene Ansichten in einem Frame anzeigen, da-runter eine Kunden&uuml;bersicht und eine Kundendetailansicht. Beim Anzeigen sollen verschiedene Dinge geschehen, die wir &uuml;ber die Implementierung von Ereignissen l&ouml;sen wollen &#8211; und zwar &uuml;ber eingebaute sowie &uuml;ber benutzerdefinierte Ereignisse.<\/b><\/p>\n<h2>Beispielprojekt<\/h2>\n<p>Im Beispiel geht es um ein Hauptfenster, das &uuml;ber zwei Ribbon-Buttons verschiedene <b>Page<\/b>-Elemente in einem Frame anzeigen soll. Die Schaltfl&auml;che <b>Kunden&uuml;bersicht <\/b>zeigt das <b>Page<\/b>-Objekt <b>Kundenuebersicht <\/b>an, die Schaltlf&auml;che <b>Neuer Kunde <\/b>das <b>Page<\/b>-Objekt <b>Kundendetails<\/b>. Diese Seite wird ebenfalls aufgerufen, wenn der Benutzer doppelt auf einen der Eintr&auml;ge der Kunden&uuml;bersicht klickt (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_06\/pic_65_001.png\" alt=\"Interaktion zwischen den einzelnen Seiten\" width=\"649,559\" height=\"407,5357\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Interaktion zwischen den einzelnen Seiten<\/span><\/b><\/p>\n<p>Im ersten Beispiel wollen wir daf&uuml;r sorgen, dass eine dritte Ribbon-Schaltfl&auml;che zum L&ouml;schen von Elementen der Kunden&uuml;bersicht nur aktiviert wird, wenn die Kunden&uuml;bersicht angezeigt wird. Das hei&szlig;t, dass diese Schaltfl&auml;che deaktiviert werden soll, wenn eine andere Ansicht als die Kunden&uuml;bersicht erscheint. Dazu wollen wir ein Ereignis implementieren, das beim Seitenwechseln im Frame-Element ausgel&ouml;st wird.<\/p>\n<p>Im zweiten Beispiel wollen wir zwei eigene Events programmieren und implementieren. Die Kunden&uuml;bersicht soll nicht jedes Mal, wenn der Benutzer von einer anderen Seite zur&uuml;ck auf diese Seite wechselt, neu erstellt werden beziehungsweise ihre Daten neu aus der Datenbank einlesen. Dies soll nur geschehen, wenn entweder einer der angezeigten Eintr&auml;ge auf der Seite <b>Kundendetails <\/b>ge&auml;ndert oder ein neuer Eintrag hinzugef&uuml;gt wurde. Dazu wollen wir ein Ereignis in der Code behind-Klasse der Seite <b>Kundendetails<\/b> programmieren, die wir dann in der Code behind-Klasse des <b>MainWindow<\/b>-Objekts implementieren.<\/p>\n<p>So k&ouml;nnen wir dann direkt im <b>MainWindow<\/b> den relevanten Code ausf&uuml;hren und m&uuml;ssen nicht von der untergeordneten Seite mit den Kundendetails auf das &uuml;bergeordnete Fenster zugreifen &#8211; den Hintergrund erl&auml;utern wir weiter unten.<\/p>\n<h2>Eingebaute Events nutzen<\/h2>\n<p>Im ersten Beispiel wollen wir also ein <b>Ribbon<\/b>-Steuerelement im <b>MainWindow <\/b>aktivieren oder deaktivieren, je nachdem welches <b>Page<\/b>-Element das <b>Frame<\/b>-Element anzeigt. Wenn es die Seite <b>Kundenuebersicht<\/b> anzeigt, soll die Schaltfl&auml;che <b>btnKundeLoeschen <\/b>aktiviert werden, wenn es eine andere Seite anzeigt, soll der Benutzer diese Schaltfl&auml;che nicht anklicken k&ouml;nnen.<\/p>\n<p>Dazu legen wir f&uuml;r das Frame-Element im XAML-Code, also in der Klasse <b>MainWindow.xaml<\/b>, das Attribut <b>Navigated <\/b>an und f&uuml;llen es mit dem Wert <b>WorkZone_Navigated<\/b>:<\/p>\n<pre>&lt;Window x:Class=\"Bestellverwaltung.MainWindow\" ...\r\n         Title=\"MainWindow\" Height=\"450\" Width=\"525\"&gt;\r\n     &lt;Grid&gt;\r\n         ...\r\n         &lt;Frame x:Name=\"WorkZone\" Grid.Row=\"1\" \r\n             Navigated=\"WorkZone_Navigated\"&gt;&lt;\/Frame&gt;\r\n     &lt;\/Grid&gt;\r\n&lt;\/Window&gt;<\/pre>\n<p>F&uuml;r dieses Ereignis hinterlegen wir die folgende Methode in der Code behind-Datei von <b>MainWindow<\/b>:<\/p>\n<pre>private void WorkZone_Navigated(object sender, \r\n         System.Windows.Navigation.NavigationEventArgs e) {\r\n     switch (WorkZone.Content.ToString()) {\r\n         case \"Bestellverwaltung.Kundenuebersicht\":\r\n             btnKundeLoeschen.IsEnabled = true;\r\n             break;\r\n         default:\r\n             btnKundeLoeschen.IsEnabled = false;\r\n             break;\r\n     }\r\n}<\/pre>\n<p>Diese Methode wird nun beim Wechseln des im Frame-Objekts angezeigten Objekts ausgel&ouml;st. Mit einer <b>switch<\/b>-Bedingung pr&uuml;fen wir den Namen des angezeigten Elements, hier mit der Eigenschaft <b>Content <\/b>ermittelt. Hat diese den Wert <b>Bestellverwaltung.Kundenuebersicht<\/b>, stellt die Methode den Wert der Eigenschaft <b>IsEnabled <\/b>des Elements <b>btnKundeLoeschen <\/b>auf <b>true <\/b>ein. F&uuml;r jeden anderen Inhalt erh&auml;lt <b>IsEnabled <\/b>den Wert <b>false<\/b>.<\/p>\n<p>Was ist nun der Unterschied zu den Ereignissen etwa einer Schaltfl&auml;che, die wir nun schon in vielen Beispielen implementiert haben In den bisherigen Beispielen haben wir meist selbst die Ereignisse ausgel&ouml;st, zum Beispiel durch einen Mausklick auf eine Schaltfl&auml;che. Diesmal wurde das Ereignis indirekt durch unsere Aktion ausgel&ouml;st, n&auml;mlich durch einen Klick auf eine Ribbon-Schaltfl&auml;che, die wiede-rum den Inhalt des <b>Frame<\/b>-Objekts ge&auml;ndert hat. Und das hat dann unser hier implementiertes Ereignis hervorgerufen.<\/p>\n<h2>Benutzerdefinierte Events<\/h2>\n<p>Wie oben gezeigt, gibt es eine gro&szlig;e Anzahl eingebauter Ereignisse, die Sie f&uuml;r Ihre Zwecke nutzen k&ouml;nnen. Nicht immer jedoch werden Ereignisse zum gew&uuml;nschten Zeitpunkt ausgel&ouml;st. Ein Beispiel ist das Speichern eines Kunden, der neu angelegt oder ge&auml;ndert wurde. Unter Access, wo alles auf die Anzeige und Bearbeitung von Daten ausgelegt ist, finden Sie entsprechende Ereignisse zuhauf &#8211; zum Beispiel das Ereignis <b>Nach Aktualisierung<\/b>. Unter WPF\/C# sorgen wir selbst daf&uuml;r, dass die &Auml;nderungen an den angezeigten Daten auch in die Datenbank geschrieben werden. Dementsprechend m&uuml;ssen wir auch selbst Ereignisse definieren, die zu einem solchen Zeitpunkt ausgel&ouml;st werden.<\/p>\n<p>In unserem Fall wollen wir ein solches Ereignis nutzen, um festzulegen, ob eine &Auml;nderung oder eine Neuanlage eines Kunden erfolgt ist. Abh&auml;ngig davon soll die Kunden&uuml;bersicht, wenn sie das n&auml;chste Mal eingeblendet wird, entweder neu erzeugt werden (falls &Auml;nderungen vorliegen) oder mit den alten Daten eingeblendet werden.<\/p>\n<p>Dazu soll das Hauptfenster eine Variable namens <b>KundenChanged <\/b>vorhalten, die lesend und schreibend zugreibar ist und wie folgt in der Klasse <b>MainWindow <\/b>deklariert wird:<\/p>\n<pre>public bool KundeChanged { get; set; }<\/pre>\n<h2>Die einfache Variante<\/h2>\n<p>Nun k&ouml;nnten wir im <b>Page<\/b>-Objekt <b>Kundendetails <\/b>die Schaltfl&auml;che <b>Speichern <\/b>mit einer Anweisung ausstatten, welche die Eigenschaft <b>KundeChanged<\/b> einfach auf den Wert <b>true <\/b>einstellt, wenn der Benutzer die Schaltfl&auml;che bet&auml;tigt hat (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_06\/pic_65_002.png\" alt=\"Ein Klick auf Speichern stellt die Eigenschaft KundeChanged im MainWindow auf true ein.\" width=\"424,7115\" height=\"368,1942\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Ein Klick auf Speichern stellt die Eigenschaft KundeChanged im MainWindow auf true ein.<\/span><\/b><\/p>\n<p>In diesem einfachen Fall sieht die Methode, die beim Anklicken der <b>Speichern<\/b>-Schaltfl&auml;che ausgel&ouml;st wird, wie in Listing 1 aus. Die erste Anweisung pr&uuml;ft, ob es sich um einen neuen Kunden handelt (in diesem Fall ist die <b>ID <\/b>noch <b>0<\/b>, da noch nicht vom Datenbanksystem vergeben). Ist der Kunde neu, wird er im ersten Teil der <b>If<\/b>-Bedingung hinzugef&uuml;gt und in der Datenbank gespeichert. Au&szlig;erdem referenzieren wir das <b>MainWindow<\/b>-Objekt &uuml;ber <b>Window.GetWindow(this) <\/b>und stellen anschlie&szlig;end seine Eigenschaft <b>KundeChanged<\/b>, die wir weiter oben als &ouml;ffentliche Variable des Fensters <b>MainWindow <\/b>deklariert haben, auf den Wert <b>True <\/b>ein. Handelt es sich um einen vorhandenen Kunden, der ge&auml;ndert wurde, speichern wir ebenfalls die &Auml;nderungen in der Datenbank und stellen dann wie oben den Wert der Eigenschaft <b>KundeChanged <\/b>auf <b>True <\/b>ein.<\/p>\n<pre>private void btnSpeichern_Click(object sender, RoutedEventArgs e) {\r\n     bool kundeCreated = kundeTemp.ID == 0;\r\n     if (kundeCreated) {\r\n         dbContext.Kunden.Add(kundeTemp);\r\n         dbContext.SaveChanges();\r\n         MainWindow wnd = \r\n             (MainWindow)Window.GetWindow(this);\r\n         wnd.KundeChanged = true;\r\n     }\r\n     else {\r\n         dbContext.SaveChanges();\r\n         MainWindow wnd = \r\n             (MainWindow)Window.GetWindow(this);\r\n         wnd.KundeChanged = true;\r\n     }\r\n}<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Beispiel f&uuml;r das Aktualisieren einer Variablen durch direkten Zugriff<\/span><\/b><\/p>\n<h2>Neu erstellen oder nicht<\/h2>\n<p>Wenn der Benutzer nun im <b>MainWindow <\/b>auf die Ribbon-Schaltfl&auml;che <b>btnKunden-uebersicht<\/b> klickt, l&ouml;st er die Ereignismethode <b>btnKundenuebersicht_Click<\/b> aus Listing 2 aus. Diese pr&uuml;ft im ersten Teil der <b>if<\/b>-Bedingung vor dem Oder-Zeichen (<b>|<\/b>), ob <b>kundenuebersicht <\/b>&uuml;berhaupt schon existiert, also nicht den Wert <b>null <\/b>enth&auml;lt &#8211; in diesem Fall wird dieses <b>Page<\/b>-Objekt auf jeden Fall neu erstellt. Der Teil hinter dem Oder-Zeichen pr&uuml;ft, ob die Boolean-Variable <b>KundeChanged <\/b>den Wert <b>true <\/b>enth&auml;lt.<\/p>\n<pre>private void btnKundenuebersicht_Click(object sender, RoutedEventArgs e) {\r\n     if (kundenuebersicht == null | KundeChanged == true) {\r\n         kundenuebersicht = new Kundenuebersicht();\r\n         KundeChanged = false;\r\n     }\r\n     WorkZone.Content = kundenuebersicht;\r\n}<\/pre>\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\/55000065\/\">\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\/55000065?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\/55000065\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"491fff03d6\"\/>\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 &#8220;Von VBA zu C#: Objekt-Ereignisse&#8221; haben wir bereits die Grundlagen zur Programmierung und Implementierung benutzerdefinierter Ereignisse gelegt. Dies wollen wir nun ausbauen, indem wir uns zwei praktische Beispiele ansehen. Dabei wollen wir von einem Hauptfenster aus verschiedene Ansichten in einem Frame anzeigen, darunter eine Kunden&uuml;bersicht und eine Kundendetailansicht. Beim Anzeigen sollen verschiedene Dinge geschehen, die wir &uuml;ber die Implementierung von Ereignissen l&ouml;sen wollen &#8211; und zwar &uuml;ber eingebaute sowie &uuml;ber benutzerdefinierte Ereignisse.<\/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":[662016,66062016,44000001,44000033],"tags":[],"yst_prominent_words":[],"class_list":["post-55000065","post","type-post","status-publish","format-standard","hentry","category-662016","category-66062016","category-CGrundlagen","category-Visual_Basic_Programmierung"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000065","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=55000065"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000065\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000065"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000065"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000065"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000065"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}