{"id":55000020,"date":"2016-02-01T00:00:00","date_gmt":"2020-03-27T19:17:02","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=20"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Von_VBA_zu_C_ObjektEreignisse","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Von_VBA_zu_C_ObjektEreignisse\/","title":{"rendered":"Von VBA zu C#: Objekt-Ereignisse"},"content":{"rendered":"<p><b>Nicht nur Fenster und Steuerelemente, sondern auch Objekte, die nicht Bestandteil der Benutzeroberfl&auml;che sind, k&ouml;nnen Ereignisse ausl&ouml;sen. Schlie&szlig;lich k&ouml;nnen Sie auch selbst Klassen programmieren und diese mit Ereignishandlern versehen. Wie Sie unter C# mit diesen M&ouml;glichkeiten umgehen, zeigt dieser Artikel. Dabei schauen wir uns zun&auml;chst an, wie Sie Ereignisse f&uuml;r Objekte auf Basis etwa der OpenFileDialog-Klasse implementieren und erstellen dann eine benutzerdefinierte Klasse mit einem Ereignishandler.<\/b><\/p>\n<h2>Ereignisse von Klassen implementieren<\/h2>\n<p>Neben Formularen und Steuerelementen bieten unter Access auch verschiedene Klassen beziehungsweise Objekte Ereignisse an, die Sie selbst implementieren k&ouml;nnen. Als Beispiel sei etwa die Klasse <b>Application <\/b>anderer Office-Anwendungen wie Outlook,Word oder Excel genannt. Sie deklarieren dabei eine entsprechende Objektvariable wie etwa <b>objWord <\/b>mit dem Typ <b>Word.Application <\/b>und instanzieren Word dann mit der <b>New<\/b>-Methode. Wenn Sie die Deklaration mit dem Schl&uuml;sselwort <b>WithEvents <\/b>durchf&uuml;hren, k&ouml;nnen Sie anschlie&szlig;end nicht nur Methoden oder Eigenschaften von Word aufrufen, sondern auch noch die Ereignisse von Word durch entsprechende Ereignisprozeduren implementieren &#8211; beispielsweise, wenn ein Dokument ge&ouml;ffnet oder geschlossen wird:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>WithEvents objWord<span style=\"color:blue;\"> As <\/span>Word.Application\r\n<span style=\"color:blue;\">Set<\/span> objWord = <span style=\"color:blue;\">New<\/span> Word.Application<\/pre>\n<p>Dazu w&auml;hlen Sie dann im linken Kombinationsfeld des VBA-Fensters, in der die Variable <b>objWord <\/b>definiert ist, den Eintrag <b>objWord <\/b>aus und k&ouml;nnen dann mit dem rechten Kombinationsfeld die zur Verf&uuml;gung stehenden Ereignisse selektieren &#8211; beispielsweise das <b>Quit<\/b>-Ereignis. Im Beispiel aus Bild 1 haben wir etwa eine Word-Instanz erstellt und unter <b>objWord <\/b>gespeichert. Die f&uuml;r das <b>Quit<\/b>-Ereignis erstellte Ereignisprozedur haben wir mit einer Anweisung gef&uuml;llt, die ein Meldungsfenster liefert, wenn die Word-Instanz wieder geschlossen wird.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_01\/pic_20_001.png\" alt=\"Implementieren eines Ereignisses eines Objekts\" width=\"500\" height=\"288,2883\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Implementieren eines Ereignisses eines Objekts<\/span><\/b><\/p>\n<h2>Ereignis unter C# implementieren<\/h2>\n<p>Unter C# l&auml;uft dies etwas anders, aber nicht viel. Im folgenden Beispiel wollen wir die <b>Timer<\/b>-Klasse verwenden (der Zugriff auf Word ist von C#-Projekten aus etwas aufw&auml;ndiger &#8211; dies schauen wir uns in einem sp&auml;teren Beitrag an &#8230;). Die <b>Timer<\/b>-Klasse erlaubt es, ein Zeitgeber-Intervall festzulegen, nach dem das Ereignis <b>Elapsed <\/b>ausgel&ouml;st wird.<\/p>\n<p>Die Objektvariable f&uuml;r das Objekt, das ein Ereignis ausl&ouml;sen soll, deklarieren wir unter C# nicht mit einem speziellen Schl&uuml;sselwort wie <b>WithEvents <\/b>unter VBA, sondern einfach als private, statische Variable:<\/p>\n<pre>private static Timer timer;<\/pre>\n<p>In der gleichen Klasse legen wir unsere Methode an, welche das Objekt auf Basis der Klasse <b>Timer <\/b>instanziert, stellen das Zeitgeber-Intervall ein und starten den Zeitgeber. Au&szlig;erdem, und das ist der wichtigste Punkt, legen wir fest, dass beim Eintreten des Ereignisses <b>Elapsed <\/b>der <b>Timer<\/b>-Klasse die Methode <b>Timer_Elapsed <\/b>ausgef&uuml;hrt werden soll. Dies erreichen wir durch die folgende Zeile:<\/p>\n<pre>timer.Elapsed += Timer_Elapsed;<\/pre>\n<p>Die komplette Prozedur zum Erstellen des <b>Timer<\/b>-Objekts und zum Starten des Zeitgebers sieht nun wie folgt aus:<\/p>\n<pre>public static void TimerEreignis() {\r\n     Console.WriteLine(\"Start Timer. Intervall: eine Sekunde.\");\r\n     timer = new Timer();\r\n     timer.Elapsed += Timer_Elapsed;\r\n     timer.Interval = 1000;\r\n     timer.Start();\r\n}<\/pre>\n<p>Nun ben&ouml;tigen wir noch die Methode, die beim Eintreten des <b>Elapsed<\/b>-Ereignisses ausgel&ouml;st wird &#8211; unter VBA haben wir diese Ereignisprozedur genannt. Diese erh&auml;lt die &auml;hnliche Signatur wie auch die Ereignisprozeduren etwa von Steuerelementen, also mit zwei Parametern namens <b>sender <\/b>und <b>e<\/b>:<\/p>\n<pre>private static void Timer_Elapsed(object sender, \r\n         ElapsedEventArgs e) {\r\n     timer.Stop();\r\n     Console.WriteLine(\"Zeit abgelaufen.\");\r\n     Console.ReadLine();\r\n}<\/pre>\n<p><b>e<\/b> hat hier allerdings den Typ <b>ElapsedEventArgs<\/b>. Dieses Objekt liefert neben den Standardelementen mit der Eigenschaft <b>SignalTime <\/b>die Zeit, zu der das Ereignis ausgel&ouml;st wurde. Dieses nehmen wir noch zur Ausgabe hinzu:<\/p>\n<pre>Console.WriteLine(\"Zeit abgelaufen. {0}\", e.SignalTime);<\/pre>\n<h2>Eigene Ereignisse programmieren<\/h2>\n<p>Nun wollen wir eine Klasse mit einem eigenen Ereignis programmieren. Ausgangspunkt ist die folgende einfache Klasse namens <b>Person <\/b>mit einer einzigen Eigenschaft namens <b>Vorname<\/b> sowie den entsprechenden <b>get<\/b>&#8211; und <b>set<\/b>-Methoden:<\/p>\n<pre>public class Person {\r\n     private string vorname;\r\n     public string Vorname {\r\n         get {\r\n             return this.vorname;\r\n         }\r\n         set {\r\n             this.vorname = value;\r\n         }\r\n     }\r\n}<\/pre>\n<p>Die folgende Methode erstellt ein neues Objekt auf Basis dieser Klasse und f&uuml;llt die Eigenschaft <b>Vorname <\/b>mit dem Wert <b>Andr&eacute;<\/b>:<\/p>\n<pre>public static void KundeErstellen() {\r\n     Person person = new Person();\r\n     person.Vorname = \"Andr&eacute;\";\r\n     Console.WriteLine(\"Vorname: {0}\", person.Vorname);\r\n     Console.ReadLine();\r\n}<\/pre>\n<p>Diese Klasse soll nun beim &Auml;ndern des Wertes der Eigenschaft Vorname ein Ereignis ausl&ouml;sen, das wir wiederum in der Klasse mit der Methode implementieren wollen. Dazu sind auf Seite der Klasse <b>Person<\/b> die folgenden Schritte n&ouml;tig:<\/p>\n<ul>\n<li>Definieren eines Delegates, der festlegt, welche Parameter die zu implementierenden Ereigisprozeduren verwenden m&uuml;ssen (und die auch beim Ausl&ouml;sen gef&uuml;llt werden),<\/li>\n<li>Definieren eines Ereignisses mit dem Schl&uuml;sselwort event, dem Typ des Ereignisses (der dem zuvor definierten Delegate entspricht) und dem Namen des Ereignisses und<\/li>\n<li>die Definition einer Methode, die der Signatur des Delegates entspricht und das Ereignis ausl&ouml;st, sofern dieses abonniert wurde und die innerhalb der Klasse beim Eintreten des jeweiligen Ereignisses &#8211; hier beim &Auml;ndern des Wertes der Eigenschaft <b>Vorname <\/b>in der entsprechenden <b>Set<\/b>-Methode &#8211; aufgerufen wird.<\/li>\n<\/ul>\n<p>Die Klasse <b>Person <\/b>wird nun also wie in Listing 1 erweitert. In der <b>get<\/b>\/<b>set<\/b>-Methode kommt nur die Zeile hinzu, welche die Methode <b>BeiEigenschaftGeaendert <\/b>aufruft. Diese &uuml;bergibt als ersten Parameter einen Verweis auf die Klasse selbst, als zweiten den Wert <b>null<\/b>. Sp&auml;ter werden wir dies noch erweitern.<\/p>\n<pre>public class Person {\r\n     private string vorname;\r\n     public string Vorname {\r\n         get {\r\n             return this.vorname;\r\n         }\r\n         set {\r\n             this.vorname = value;\r\n             BeiEigenschaftGeaendert(this, null);\r\n         }\r\n     }\r\n     public delegate void EigenschaftGeaendertEventHandler(object sender, EventArgs e);\r\n     public event EigenschaftGeaendertEventHandler EigenschaftGeaendert;\r\n     protected void BeiEigenschaftGeaendert(object sender, EventArgs e) {\r\n         if(EigenschaftGeaendert != null) {\r\n             EigenschaftGeaendert(this, e);\r\n         }\r\n     }\r\n}<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Die Klasse Person mit einem Ereignis, das beim &Auml;ndern einer Eigenschaft feuert<\/span><\/b><\/p>\n<p>Das <b>delegate<\/b>-Objekt namens <b>EigenschaftGeaendertEvent-Handler <\/b>enth&auml;lt die Signatur f&uuml;r die zu implementierende Ereignisprozedur. Die Namen aller Delegates, die als Typ eines <b>event<\/b>-Objekts herangezogen werden, sollen auf <b>Event-Handler <\/b>enden.<\/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\/55000020\/\">\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\/55000020?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\/55000020\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"349bc4cffe\"\/>\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>Nicht nur Fenster und Steuerelemente, sondern auch Objekte, die nicht Bestandteil der Benutzeroberfl&auml;che sind, k&ouml;nnen Ereignisse ausl&ouml;sen. Schlie&szlig;lich k&ouml;nnen Sie auch selbst Klassen programmieren und diese mit Ereignishandlern versehen. Wie Sie unter C# mit diesen M&ouml;glichkeiten umgehen, zeigt dieser Artikel. Dabei schauen wir uns zun&auml;chst an, wie Sie Ereignisse f&uuml;r Objekte auf Basis etwa der OpenFileDialog-Klasse implementieren und erstellen dann eine benutzerdefinierte Klasse mit einem Ereignishandler.<\/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":[66012016,662016,44000024,44000001],"tags":[],"yst_prominent_words":[66062022,66062023,66062049,66062051,66062047,66062053],"class_list":["post-55000020","post","type-post","status-publish","format-standard","hentry","category-66012016","category-662016","category-Berichte_und_Reporting","category-CGrundlagen"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000020","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=55000020"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000020\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000020"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000020"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000020"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000020"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}