{"id":55000062,"date":"2016-12-01T00:00:00","date_gmt":"2020-03-27T19:23:19","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=62"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"WPFTrigger","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/WPFTrigger\/","title":{"rendered":"WPF-Trigger"},"content":{"rendered":"<p><b>Trigger kennt der geneigte Access-Anwender h&ouml;chstens vom SQL Server, wo diese die M&ouml;glichkeit boten, auf &Auml;nderungen in den Tabellen zu reagieren, f&uuml;r die sie angelegt wurden. Ein Konstrukt namens Trigger gibt es aber auch unter WPF. Dort sind Trigger nicht an Tabellen gebundene Algorithmen, sondern Definitionen von Aktionen, die in Zusammenhang mit Daten&auml;nderungen ausgel&ouml;st werden. Dieser Artikel stellt Trigger und ihre Anwendungsm&ouml;glichkeiten vor.<\/b><\/p>\n<h2>Trigger-Arten<\/h2>\n<p>Es gibt drei Arten von Triggern, von denen zwei aktuell f&uuml;r uns interessant sind. Der Vollst&auml;ndigkeit halber sollen hier jedoch dennoch alle drei Arten aufgef&uuml;hrt werden:<\/p>\n<ul>\n<li>Eigenschaftstrigger (Property Trigger): Werden ausgel&ouml;st, wenn sich der Wert einer Eigenschaft &auml;ndert. Arbeitet nur mit Dependency Properties. Kann nur Eigenschaften des betroffenen Elements &auml;ndern und dabei nur auf Eigenschaften des gleichen Elements zugreifen.<\/li>\n<li>Datentrigger (Data Trigger): Wie Eigenschaftstrigger, allerdings auch f&uuml;r andere Eigenschaften als Dependency Properties. Als Quelle kann auch ein anderes Element als das mit dem Trigger versehene Element dienen. Die wichtigste Eigenschaft von Dependency Properties, die hier interessant ist, ist die automatische Information von daran gebundenen Elementen &uuml;ber einen ge&auml;nderten Zustand des Wertes der Property.<\/li>\n<li>Ereignistrigger (Event Trigger): Werden zum Beispiel verwendet, um Animationen zu starten und zu beenden, wenn bestimmte Ereignisse eintreten. Um diese Art von Triggern k&uuml;mmern wir uns in einem sp&auml;teren Artikel.<\/li>\n<\/ul>\n<h2>Eigenschaftstrigger (Property Trigger)<\/h2>\n<p>Gleich zu Beginn zeigen wir Ihnen, dass Sie Trigger ganz einfach statt einfacher C#-Ereignismethoden einsetzen k&ouml;nnen. Im Beispiel wollen wir die aktive Schaltfl&auml;che jeweils mit einem hellgelben Hintergrund versehen. Dazu definieren wir unseren XAML-Code wie folgt (siehe Beispielprojekt, Seite <b>TriggerPerCSharpEreignis.xaml<\/b>):<\/p>\n<pre>&lt;Grid&gt;\r\n     &lt;Grid.ColumnDefinitions&gt;\r\n         &lt;ColumnDefinition Width=\"Auto\"&gt;&lt;\/ColumnDefinition&gt;\r\n         &lt;ColumnDefinition&gt;&lt;\/ColumnDefinition&gt;\r\n     &lt;\/Grid.ColumnDefinitions&gt;\r\n     &lt;Grid.RowDefinitions&gt;\r\n         &lt;RowDefinition Height=\"Auto\"&gt;&lt;\/RowDefinition&gt;\r\n         &lt;RowDefinition Height=\"Auto\"&gt;&lt;\/RowDefinition&gt;\r\n     &lt;\/Grid.RowDefinitions&gt;\r\n     &lt;Label Content=\"Vorname:\" Margin=\"5\"&gt;&lt;\/Label&gt;\r\n     &lt;TextBox x:Name=\"txtVorname\" ... GotFocus=\"txtVorname_GotFocus\" LostFocus=\"txtVorname_LostFocus\"&gt;&lt;\/TextBox&gt;\r\n     &lt;Label Content=\"Nachname:\" Margin=\"5\" Grid.Row=\"1\"&gt;&lt;\/Label&gt;\r\n     &lt;TextBox x:Name=\"txtNachname\" ... GotFocus=\"txtNachname_GotFocus\" LostFocus=\"txtNachname_LostFocus\"&gt;&lt;\/TextBox&gt;\r\n&lt;\/Grid&gt; <\/pre>\n<p>F&uuml;r die vier f&uuml;r die beiden Textfelder definierten Ereignisattribute hinterlegen wir die folgenden vier Ereignismethoden im Code behind-Modul:<\/p>\n<pre>private void txtVorname_GotFocus(object sender, RoutedEventArgs e) {\r\n     txtVorname.Background = Brushes.LightYellow;\r\n}\r\nprivate void txtVorname_LostFocus(object sender, RoutedEventArgs e) {\r\n     txtVorname.Background = null;\r\n}\r\nprivate void txtNachname_GotFocus(object sender, RoutedEventArgs e) {\r\n     txtNachname.Background = Brushes.LightYellow;\r\n}\r\nprivate void txtNachname_LostFocus(object sender, RoutedEventArgs e) {\r\n     txtNachname.Background = null;\r\n}<\/pre>\n<p>Dies sorgt daf&uuml;r, dass das jeweilige Textfeld bei Fokuserhalt jeweils auf die Hintergrundfarbe <b>LightYellow <\/b>eingestellt wird. Bei Fokusverlust leeren wir die Eigenschaft <b>Background <\/b>wieder, indem wir diese auf den Wert <b>null <\/b>einstellen.<\/p>\n<p> Dies ergibt ein Fenster wie in Bild 1.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_06\/pic_62_001.png\" alt=\"Fenster mit zwei Textfeldern, von denen das aktive jeweils einen gelben Hintergrund erh&auml;lt\" width=\"499,6607\" height=\"149,1382\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Fenster mit zwei Textfeldern, von denen das aktive jeweils einen gelben Hintergrund erh&auml;lt<\/span><\/b><\/p>\n<h2>Eigenschafts&auml;nderung per XAML<\/h2>\n<p>Dies k&ouml;nnen Sie auch ohne C#-Code erreichen, allerdings mit etwas mehr Schreibaufwand. &Auml;ndern Sie den Code f&uuml;r die erste TextBox wie folgt (Beispielprojekt, Seite <b>PropertyTrigger.xaml<\/b>):<\/p>\n<pre>&lt;TextBox x:Name=\"txtVorname\" Grid.Row=\"1\" Grid.Column=\"1\" Margin=\"5\"&gt;\r\n     &lt;TextBox.Style&gt;\r\n         &lt;Style TargetType=\"{x:Type TextBox}\"&gt;\r\n             &lt;Style.Triggers&gt;\r\n                 &lt;Trigger Property=\"IsFocused\" Value=\"True\"&gt;\r\n                     &lt;Setter Property=\"Background\" Value=\"LightYellow\"&gt;&lt;\/Setter&gt;\r\n                 &lt;\/Trigger&gt;\r\n             &lt;\/Style.Triggers&gt;\r\n         &lt;\/Style&gt;\r\n     &lt;\/TextBox.Style&gt;\r\n&lt;\/TextBox&gt;<\/pre>\n<p>Die wesentlichen Elemente hier sind die folgenden:<\/p>\n<pre>&lt;Trigger Property=\"IsFocused\" Value=\"True\"&gt;\r\n     &lt;Setter Property=\"Background\" Value=\"LightYellow\"&gt;&lt;\/Setter&gt;\r\n&lt;\/Trigger&gt;<\/pre>\n<p>Wir setzen einen Trigger, der ausgel&ouml;st werden soll, wenn die Eigenschaft <b>IsFocused <\/b>den Wert <b>True <\/b>enth&auml;lt. Dann soll eine weitere Eigenschaft namens <b>Background <\/b>auf den Wert <b>LightYellow <\/b>eingestellt werden. Das Drumherum ben&ouml;tigen wir, um den Trigger f&uuml;r die Textbox verf&uuml;gbar zu machen. In diesem Fall legen wir ein <b>Style<\/b>-Objekt f&uuml;r die <b>Style<\/b>-Eigenschaft der Textbox an (<b>TextBox.Style<\/b>), der wir in der <b>Triggers<\/b>-Auflistung den obigen Trigger bekannt machen.<\/p>\n<p>Wenn wir der zweiten Textbox genau den gleichen Trigger unterschieben, erhalten wir genau das gleiche Verhalten wie beim ersten Beispiel, wo wir die &Auml;nderung des Hintergrunds noch mit C#-Ereignismethoden realisiert haben.<\/p>\n<p>Welche Vorteile liefert uns diese Vorgehensweise Aktuell nur den, dass wir das Code behind-Modul nicht aufblasen. Stattdessen haben wir aber einigen Code mehr im <b>.xaml<\/b>-Modul. Bei beiden Varianten h&auml;tten wir noch viel mehr Code, wenn wir dieses Verhalten f&uuml;r weitere Textfelder implementieren wollten. Das k&ouml;nnen wir aber in beiden F&auml;llen &auml;ndern. <\/p>\n<p>Ein weiterer Vorteil ist, dass die Eigenschaften immer &uuml;berwacht werden und der Zustand auch wieder r&uuml;ckg&auml;ngig gemacht wird, wenn die Bedingung nicht mehr erf&uuml;llt ist. Verliert das erste <b>TextBox<\/b>-Element also den Fokus, ist <b>IsFocused <\/b>nicht mehr <b>True<\/b>, also wird auch der Wert f&uuml;r die dadurch ge&auml;nderte Eigenschaft <b>Background <\/b>wieder zur&uuml;ckgenommen.<\/p>\n<h2>Property-Trigger per Ressource<\/h2>\n<p>Wenn wir davon ausgehen, dass alle <b>TextBox<\/b>-Elemente eines Fensters (oder, wie in diesem Fall, einer Seite) das gleiche Verhalten implementieren sollen, k&ouml;nnen wir den Style mit dem Trigger auch in den Ressourcen des Fensters\/der Seite festlegen. Die Trigger-Definitionen f&uuml;r die einzelnen Steuerelemente k&ouml;nnen Sie dann entfernen. Der Vorteil ist, dass Sie nun beliebig viele Textfelder hinzuf&uuml;gen k&ouml;nnen &#8211; alle werden beim Fokuserhalt gelb hinterlegt. Der ben&ouml;tigte Code sieht so aus (siehe Beispielprojekt, Seite <b>PropertyTrigger_Resource.xaml<\/b>) und wird direkt unterhalb des <b>Page<\/b>-Elements eingef&uuml;gt:<\/p>\n<pre>&lt;Page.Resources&gt;\r\n     &lt;Style TargetType=\"{x:Type TextBox}\"&gt;\r\n         &lt;Style.Triggers&gt;\r\n             &lt;Trigger Property=\"IsFocused\" Value=\"True\"&gt;\r\n                 &lt;Setter Property=\"Background\" Value=\"LightYellow\"&gt;&lt;\/Setter&gt;\r\n             &lt;\/Trigger&gt;\r\n         &lt;\/Style.Triggers&gt;\r\n     &lt;\/Style&gt;\r\n&lt;\/Page.Resources&gt;<\/pre>\n<h2>Data Trigger<\/h2>\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\/55000062\/\">\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\/55000062?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\/55000062\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"22c77db969\"\/>\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>Trigger kennt der geneigte Access-Anwender h&ouml;chstens vom SQL Server, wo diese die M&ouml;glichkeit boten, auf &Auml;nderungen in den Tabellen zu reagieren, f&uuml;r die sie angelegt wurden. Ein Konstrukt namens Trigger gibt es aber auch unter WPF. Dort sind Trigger nicht an Tabellen gebundene Algorithmen, sondern Definitionen von Aktionen, die in Zusammenhang mit Daten&auml;nderungen ausgel&ouml;st werden. Dieser Artikel stellt Trigger und ihre Anwendungsm&ouml;glichkeiten vor.<\/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,44000021,44000003],"tags":[],"yst_prominent_words":[],"class_list":["post-55000062","post","type-post","status-publish","format-standard","hentry","category-662016","category-66062016","category-CGrundlagen","category-Entity_Framework","category-WPFGrundlagen"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000062","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=55000062"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000062\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000062"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000062"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000062"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000062"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}