HowTo: Behaviors/Triggers richtig einsetzen
Mit Expression Blend 3 ist ein neues Konzept gekommen, das definitiv eine großartige Erweiterung des Funktionsumfangs von WPF und Silverlight darstellt. Hat man bisher fehlende Funktionalität eines UI Controls über Umwege erstellt (zb das Ausfrühen von Commands, sobald ein RoutedEvent eines Controls auftritt), kann man das realtiv einfach und zentral verwalten: die Rede ist von den Behaviors und Triggers!
Was sind Behaviors und Triggers?
Es handelt sich um ein Konzept, gewisse Funktionalität zentral auszulagen und später auf jedes UI Control anzuhängen. Wann, was und wie das Behavior bzw. der Trigger die Dinge erledigt spielt keine Rolle bzw. entscheidet das Behavior bzw. der Trigger von selbst. Unterschieden wird zwischen drei unterschiedlichen Typen:
- Behavior: Diese Klasse ist die am meisten verwendete. Dabei implementiert das Behavior selbst vollkommen autonom was wann und wie passieren soll. Das UI Control, dass das Behavior verwendet hat keinerlei Kontrolle darüber, was im Behavior selbst passiert.
- TriggerAction: Diese Klasse wird direkt an einen RoutedEvent gehängt und aufgerufen, sobald dieser Event auftritt.
- TargetedTriggerAction: Diese Klasse ist der TriggerAction sehr ähnlich — jedoch kann dabei ein anderes UI Control beim RoutedEvent verändert werden
Alle drei Klassen haben generische Gegenstücke, bei denen noch expilizit das UI Control angegeben werden kann, für das das Behavior verwendet werden kann.
Custom Behavior erstellen!
Wir wollen uns nun ein eigenes Behavior erstellen, das relativ einfach ist, aber ein, meiner Meinung nach, gängies Problem lösen soll. Es soll die Maus verändern, sobald der Benutzer über einen Control bewegt, das angeklickt werden kann. Funktionaliätit, die es im Web schon lange gibt, auf Rich Client Anwendungen aber fehlt.
Als erstes erstellen wir uns eine Klasse, die von Behavior ableitet. Behavior liegt im Assembly System.Windows.Interactivity, dass standarmäßig nicht inkludiert ist. Zu finden sollte es unter
%Progam Files%\Microsoft SDKs\Expression\Blend 3\Interactivity\Libraries\WPF (oder Silverlight)
sein. Haben wir die Klasse, können wir unterschiedliche Methoder überschreiben. Die zwei wichtigsten für unser Demo sind OnAttached() und OnDetaching(). In OnAttached registrieren wir uns Eventhandler für die Events MouseEnter und MouseLeave. Im OnDetaching entfernen wir diese Eventhandler wieder.
Betritt nun die Maus das Control, wird der Eventhandler für MouseEnter aufgerufen, in dem wir den Mauszeiger verändern. In MouseLeave setzen wir ihn wieder auf den Standard zurückgesetzt. Ganz einfach eigentlich.
public class ClickableBehavior : Behavior<FrameworkElement>
{
protected override void OnAttached()
{
this.AssociatedObject.MouseEnter += new MouseEventHandler(_MouseEnter);
this.AssociatedObject.MouseLeave += new MouseEventHandler(_MouseLeave);
base.OnAttached();
}
protected override void OnDetaching()
{
this.AssociatedObject.MouseEnter -= new MouseEventHandler(_MouseEnter);
this.AssociatedObject.MouseLeave -= new MouseEventHandler(_MouseLeave);
base.OnDetaching();
}
/// <summary>
/// Der Typ des Cursos, auf den das Behavior wechsel soll.
/// </summary>
public Cursor EnterCursor
{
get { return (Cursor)GetValue(EnterCursorProperty); }
set { SetValue(EnterCursorProperty, value); }
}
public static readonly DependencyProperty EnterCursorProperty =
DependencyProperty.Register("EnterCursor", typeof(Cursor),
typeof(ClickableBehavior), new UIPropertyMetadata(Cursors.Hand));
#region Eventhandler
/// <summary>
/// Wird aufgerufen, sobald die Maus das FrameworkElement betritt.
/// </summary>
private void _MouseEnter(object sender, MouseEventArgs e)
{
this.AssociatedObject.Cursor = EnterCursor;
}
/// <summary>
/// Wird aufgerufen, sobald die Maus das FrameworkElement verlässt.
/// </summary>
private void _MouseLeave(object sender, MouseEventArgs e)
{
this.AssociatedObject.Cursor = null;
}
#endregion Eventhandler
}
Nachdem wir die Logik nun haben, können wir das Behavior jetzt verwenden. Das tun wir, indem wir im XAML Code zuerst den richtigen Namespace einbinden (System.Windows.Interactivity und unseren lokalen Namespace) und dann auf ein beliebiges Control das Behavior anfügen:
<Grid Margin="50" Background="Gold">
<interactivity:Interaction.Behaviors>
<local:ClickableBehavior />
</interactivity:Interaction.Behaviors>
</Grid>
Das Demoprojekt kann wie immer hier heruntergeladen werden: Download Demoprojekt (VS 2010 Solution).
In diesem Sinne.
