WPF-Trigger

Wenn Sie ein Abonnement des Magazins 'DATENBANKENTWICKLER' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

WPF-Trigger

Trigger kennt der geneigte Access-Anwender höchstens vom SQL Server, wo diese die Möglichkeit boten, auf Änderungen in den Tabellen zu reagieren, fü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änderungen ausgelöst werden. Dieser Artikel stellt Trigger und ihre Anwendungsmöglichkeiten vor.

Trigger-Arten

Es gibt drei Arten von Triggern, von denen zwei aktuell für uns interessant sind. Der Vollständigkeit halber sollen hier jedoch dennoch alle drei Arten aufgeführt werden:

  • Eigenschaftstrigger (Property Trigger): Werden ausgelöst, wenn sich der Wert einer Eigenschaft ändert. Arbeitet nur mit Dependendy Properties. Kann nur Eigenschaften des betroffenen Elements ändern und dabei nur auf Eigenschaften des gleichen Elements zugreifen.
  • Datentrigger (Data Trigger): Wie Eigenschaftstrigger, allerdings auch fü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 über einen geänderten Zustand des Wertes der Property.
  • Ereignistrigger (Event Trigger): Werden zum Beispiel verwendet, um Animationen zu starten und zu beenden, wenn bestimmte Ereignisse eintreten. Um diese Art von Triggern kümmern wir uns in einem späteren Artikel.

Eigenschaftstrigger (Property Trigger)

Gleich zu Beginn zeigen wir Ihnen, dass Sie Trigger ganz einfach statt einfacher C#-Ereignismethoden einsetzen können. Im Beispiel wollen wir die aktive Schaltfläche jeweils mit einem hellgelben Hintergrund versehen. Dazu definieren wir unseren XAML-Code wie folgt (siehe Beispielprojekt, Seite TriggerPerCSharpEreignis.xaml):

<Grid>
     <Grid.ColumnDefinitions>
         <ColumnDefinition Width="Auto"></ColumnDefinition>
         <ColumnDefinition></ColumnDefinition>
     </Grid.ColumnDefinitions>
     <Grid.RowDefinitions>
         <RowDefinition Height="Auto"></RowDefinition>
         <RowDefinition Height="Auto"></RowDefinition>
     </Grid.RowDefinitions>
     <Label Content="Vorname:" Margin="5"></Label>
     <TextBox x:Name="txtVorname" ... GotFocus="txtVorname_GotFocus" LostFocus="txtVorname_LostFocus"></TextBox>
     <Label Content="Nachname:" Margin="5" Grid.Row="1"></Label>
     <TextBox x:Name="txtNachname" ... GotFocus="txtNachname_GotFocus" LostFocus="txtNachname_LostFocus"></TextBox>
</Grid> 

Für die vier für die beiden Textfelder definierten Ereignisattribute hinterlegen wir die folgenden vier Ereignismethoden im Code behind-Modul:

private void txtVorname_GotFocus(object sender, RoutedEventArgs e) {
     txtVorname.Background = Brushes.LightYellow;
}
private void txtVorname_LostFocus(object sender, RoutedEventArgs e) {
     txtVorname.Background = null;
}
private void txtNachname_GotFocus(object sender, RoutedEventArgs e) {
     txtNachname.Background = Brushes.LightYellow;
}
private void txtNachname_LostFocus(object sender, RoutedEventArgs e) {
     txtNachname.Background = null;
}

Dies sorgt dafür, dass das jeweilige Textfeld bei Fokuserhalt jeweils auf die Hintergrundfarbe LightYellow eingestellt wird. Bei Fokusverlust leeren wir die Eigenschaft Background wieder, indem wir diese auf den Wert null einstellen.

Dies ergibt ein Fenster wie in Bild 1.

Fenster mit zwei Textfeldern, von denen das aktive jeweils einen gelben Hintergrund erhält

Bild 1: Fenster mit zwei Textfeldern, von denen das aktive jeweils einen gelben Hintergrund erhält

Eigenschaftsänderung per XAML

Dies können Sie auch ohne C#-Code erreichen, allerdings mit etwas mehr Schreibaufwand. Ändern Sie den Code für die erste TextBox wie folgt (Beispielprojekt, Seite PropertyTrigger.xaml):

<TextBox x:Name="txtVorname" Grid.Row="1" Grid.Column="1" Margin="5">
     <TextBox.Style>
         <Style TargetType="{x:Type TextBox}">
             <Style.Triggers>
                 <Trigger Property="IsFocused" Value="True">
                     <Setter Property="Background" Value="LightYellow"></Setter>
                 </Trigger>
             </Style.Triggers>
         </Style>
     </TextBox.Style>
</TextBox>

Die wesentlichen Elemente hier sind die folgenden:

<Trigger Property="IsFocused" Value="True">
     <Setter Property="Background" Value="LightYellow"></Setter>
</Trigger>

Wir setzen einen Trigger, der ausgelöst werden soll, wenn die Eigenschaft IsFocused den Wert True enthält. Dann soll eine weitere Eigenschaft namens Background auf den Wert LightYellow eingestellt werden. Das Drumherum benötigen wir, um den Trigger für die Textbox verfügbar zu machen. In diesem Fall legen wir ein Style-Objekt für die Style-Eigenschaft der Textbox an (TextBox.Style), der wir in der Triggers-Auflistung den obigen Trigger bekannt machen.

Wenn wir der zweiten Textbox genau den gleichen Trigger unterschieben, erhalten wir genau das gleiche Verhalten wie beim ersten Beispiel, wo wir die Änderung des Hintergrunds noch mit C#-Ereignismethoden realisiert haben.

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 .xaml-Modul. Bei beiden Varianten hätten wir noch viel mehr Code, wenn wir dieses Verhalten für weitere Textfelder implementieren wollten. Das können wir aber in beiden Fällen ändern.

Ein weiterer Vorteil ist, dass die Eigenschaften immer überwacht werden und der Zustand auch wieder rückgängig gemacht wird, wenn die Bedingung nicht mehr erfüllt ist. Verliert das erste TextBox-Element also den Fokus, ist IsFocused nicht mehr True, also wird auch der Wert für die dadurch geänderte Eigenschaft Background wieder zurückgenommen.

Property-Trigger per Ressource

Wenn wir davon ausgehen, dass alle TextBox-Elemente eines Fensters (oder, wie in diesem Fall, einer Seite), das gleiche Verhalten implementieren sollen, können wir den Style mit dem Trigger auch in den Ressourcen des Fensters/der Seite festlegen. Die Trigger-Definitionen für die einzelnen Steuerelemente können Sie dann entfernen. Der Vorteil ist, dass Sie nun beliebig viele Textfelder hinzufügen können – alle werden beim Fokuserhalt gelb hinterlegt. Der benötigte Code sieht so aus (siehe Beispielprojekt, Seite PropertyTrigger_Resource.xaml) und wird direkt unterhalb des Page-Elements eingefügt:

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.