Wie
hier bereits beschrieben, haben
Expression Blend Behaviors gegenüber Attached Properties einige Vorteile. Hierzu zählt vor allem die Designer-Unterstützung in Blend. Ein weiterer Vorteil ist jedoch auch die Tatsache, dass Behaviors mit mehreren Elementen verbunden werden können.
Ein einfaches Beispiel:Ein Dialog enthält eine Textbox/Button-Kombination zur Auswahl einer Datei.
Klassischerweise würde man hier im Code-Behind den Dateidialog öffnen und die Auswahl in die daneben stehende Textbox übertragen. Da dies eine Funktionalität ist, die häufiger benötigt wird, bietet es sich an sie zu kapseln. Der Code-Behind-Ansatz ist jedoch auch in MVVM-Szenarien ein Problem. Das Öffnen des Dialogs möchte man jedoch auch nicht im ViewModel hinterlegen, da es sich um UI-Code handelt.
Das Open File Behavior
Mit einem Behavior lässt sich solch eine Funktionalität sehr komfortabel abbilden.
TT.UIA bietet hierfür die Klasse
OpenFileBehavior. Sie leitet von
TargettetTriggerAction<T> ab und kann somit nicht nur ein Element (der Button im oberen Beispiel), sondern auch an ein Zielelement (die Textbox) gebunden werden.
...
<Button
xmlns:i=
"clr-namespace:System.Windows.Interactivity;
assembly=System.Windows.Interactivity"
xmlns:behaviors=
"clr-namespace:Thinktecture.UIAnnotations.Behaviors;
assembly=Thinktecture.UIAnnotations">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<behaviors:OpenFileBehavior
TargetName="imageTextBox"
DialogTitle="Select an image..."
Filter="PNG Files|*.png" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<TextBox x:Name="imageTextBox" />
...
Die Deklaration erfolgt hierbei über die Klasse
System.Windows.Interactivity.Interaction, die Teil des
Expression Blend SDKs ist.
Das Busy Behavior
Ein weiteres Problem in MVVM-Anwendungen ist der Umgang mit Cursorn und anderen Fortschrittsanzeigen. Denn das ViewModel sollte weder explizit einen Cursors setzen, noch ein entsprechendes UI-Element direkt steuern. In Silverlight löst man dies meist mit dem beliebten (wenn auch hässlichen) BusyIndicator, die per Data Binding an das ViewModel gebunden wird. Hierfür muss die Komponente jedoch zur Entwurfszeit in das Layout des jeweiligen Fensters so eingefügt werden, dass sie im Vordergrund steht. Dies verursacht bei nachträglichen Layout-Änderungen häufig Probleme. Zudem sollte die Bedienung des Fensters verhindert werden, sobald der BusyIndicator aktiv wird.
All diese Herausforderungen versucht die Klasse *BusyBehavior* zu lösen. Sie zeigt eine überdimensionale Eieruhr und legt dabei einen Overlay über das zugehörige Fenster um die Bedienung der Oberfläche durch den Benutzer zu verhindern. Das Busy Behavior kann mit einem beliebigen Element verknüpft werden. Es ermittelt zur Laufzeit das übergeordnete Fenster und fügt sich auf oberster Ebene in den visuellen Baum ein.
<i:Interaction.Behaviors>
<behaviors:BusyBehavior
IsBusy="{Binding IsBusy}" />
</i:Interaction.Behaviors>
Die Steuerung erfolgt über die Eigenschaft *IsBusy*, die zum Beispiel an eine entsprechende Eigenschaft des zugehörigen ViewModels gebunden werden kann. Das Ganze sieht dann zur Laufzeit in etwas so aus:
Das Dialog Button Behavior
Die Klasse
DialogButtonBehavior steuert das Verhalten von Dialogschaltflächen. Klassischerweise hat ein Dialog einen
Accept- und einen
Cancel-Button, womit der Benutzer das Fenster mit
Enter bestätigen, bzw. mit
ESC abbrechen kann. Hierbei wird das Fenster geschlossen und die
DialogResult-Eigenschaft entsprechend gesetzt. All dies fasst
DialogButtonBehavior zusammen, wie das folgende Beispiel zeigt:
<Button>
<i:Interaction.Behaviors>
<behaviors:DialogButtonBehavior ButtonType="Ok" />
</i:Interaction.Behaviors>
</Button>
Über die Eigenschaft
ButtonType kann das entsprechende Verhalten definiert werden.
Das Focus Behavior
Die Klasse
FocusBehavior markiert das fokussierte Eingabeelement mit einer beliebigen Hintergrundfarbe.
<TextBox>
<i:Interaction.Behaviors>
<behaviors:FocusBehavior HighlightBrush="Yellow" />
</i:Interaction.Behaviors>
</TextBox>
So, das war’s erstmal mit den Behaviors von
TT.UIA. Im nächsten Post gehe ich auf die
Behavior Factories ein, mit denen einige Limitationen der Behaviors behoben werden können.
Labels: TT.UIA