Kolumne: Silverlight Expertise

Automatische Aktualisierung vom Data Binding MVVM mit ReactiveUI und das Erstellen von Live Tile
Kommentare

Die Silverlight-Kolumne „Silverlight Expertise“ des dot.NET Magazins präsentiert monatlich zwei leckere Top-How-tos zum Thema Silverlight von Gregor Biswanger (www.dotnet-blog.net), sodass Einsteiger und Silverlight-Experten durch geballtes Wissen gesättigt werden. Neu dazu kommt jeweils ein How-to zur Windows-Phone-7-Entwicklung. Heute stehen auf der Menükarte „Automatische Aktualisierung vom Data Binding“, „MVVM mit ReactiveUI“ und „Live Tile erstellen“. Viel Spaß und einen guten Appetit!

Menü 1 für Einsteiger: automatische Aktualisierung vom Data Binding

In WPF werden gebundene Elemente immer per Default (PropertyChanged) sofort aktualisiert. Unter Silverlight sieht es leider etwas anders aus, denn hier wird die Aktualisierung vom Data Binding erst bei einem LostFocus ausgeführt. Oft werden die Daten sofort zur Eingabezeit benötigt, um Validierungen oder Web-Service-Aufrufe auszuführen. Erst ab Silverlight 5 steht auch ein PropertyChanged mittels UpdateSourceTrigger zur Verfügung. Hier muss im XAML beim Data Binding nur zusätzlich folgende Option deklariert werden: . Ältere Silverlight-Versionen können mit einem selbstgeschriebenen Attached Property oder durch ein Behavior erweitert werden. Das folgende Beispiel zeigt ein selbstgeschriebenes Behavior für Expression Blend. Dazu wird eine neue Klasse namens AutoUpdateSourceTextBoxBehavior erstellt. Dann müssen folgende Assemblies aus dem Expression-Blend-SDK-Verzeichnis referenziert werden:

Microsoft.Expression.Interactions.dll und System.Windows.Interactivity.dll. Anschließend wird von der Basisklasse Behavior abgeleitet. Wobei als Generic Type eine TextBox definiert wird. Dann wird mittels override die OnAttached-Methode überschrieben. In ihr wird auf die zugehörige TextBox das TextChanged-Event abonniert. Wird dann ein TextChanged ausgelöst, soll eine BindingExpression-Instanz passend zum aktuellen Control ein UpdateSource ausführen. Der Sourcecode befindet sich in Listing 1. Damit nun in Expression Blend das Behavior verwendet werden kann, muss die Assembly mit dem selbstgeschriebenen Behavior im Projekt referenziert sein. Anschließend steht unter ASSETS | BEHAVIORS das neue AutoUpdateSourceTextBoxBehavior zur Verfügung. Es kann dann über jedes TextBox-Element mittels Drag and Drop vergeben werden und wird automatisch um die selbstgeschriebene Funktion erweitert.

Listing 1: Das AutoUpdateSourceTextBoxBehavior

public class AutoUpdateSourceTextBoxBehavior : Behavior
{
    protected override void OnAttached()
    {
        AssociatedObject.TextChanged += OnTextChanged;
 
        base.OnAttached();
    }

    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        TextBox textBox = (TextBox)sender;
        BindingExpression bindingExpression = textBox.GetBindingExpression(TextBox.TextProperty);

        if (bindingExpression != null)
            bindingExpression.UpdateSource();
    }
}
  
Menü 2 für Experten: MVVM mit ReactiveUI

Microsoft DevLabs hat ein Framework veröffentlicht, mit dem asynchrone und eventbasierte Vorgänge reaktiv mittels LINQ gehandhabt werden können. Dieses Framework heißt Reactive Extensions (Rx), ist auch unter der Bezeichnung „LINQ to Events“ bekannt und kann kostenlos heruntergeladen werden. Mit ihm steht ein mächtiges Werkzeug bereit, das gerade bei asynchronen und eventbasierten Vorgängen seine Stärke ausspielen kann. Ein kostenfreier Video-Webcast mit einer Einführung zu Reactive Extensions kann Online auf MSDN bezogen werden [1]. Passend dazu bietet sich RactiveUI [2] als optimale Lösung für WPF und Silverlight an. Denn ReactiveUI ist ein Open-Source-MVVM-Framework, das explizit für eine reaktive Programmierung mit Rx ausgelegt wurde. Es bietet die Standardfeatures, die für das MVVM-Pattern benötigt werden. Es kann die Oberfläche typsicher mittels PropertyChanged informieren und auf beliebige Commands reagieren. Das Besondere an ReactiveUI ist, dass die Daten im ViewModel mittels IObservable gebunden werden können. Auch fertige Behaviors für Expression Blend sind im Paket enthalten. Listing 2 zeigt die Verwendung von ReactiveUI im ViewModel und die Stärke bei der Verwendung von Rx. Als Beispiel soll eine Silverlight-Anwendung mit drei TextBox-Controls und einem Button dienen. Die Aufgabe dazu lautet, dass der Button erst aktiv sein darf, wenn in jeder TextBox ein Text enthalten ist. Das Wichtigste dabei ist, dass es gleichgültig sein muss, in welcher Reihenfolge die TextBox-Controls verwendet werden.

Listing 2: Ein ViewModel mit ReactiveUI

public class DefaultViewModel : ReactiveObject
{
    private string _textOne;
    public string TextOne
    {
        get { return _textOne; }
        set
        {
            _textOne = value;
            this.RaisePropertyChanged(x => x.TextOne);
        }
    }

    private string _textTwo;
    public string TextTwo
    {
        get { return _textTwo; }
        set
        {
            _textTwo = value;
            this.RaisePropertyChanged(x => x.TextTwo);
        }
    }

    private string _textThree;
    public string TextThree
    {
        get { return _textThree; }
        set
        {
            _textThree = value;
            this.RaisePropertyChanged(x => x.TextThree);
        }
    }

    private bool _isButtonActive;
    public bool IsButtonActive
    {
        get { return _isButtonActive; }
        set
        {
            _isButtonActive = value;
            this.RaisePropertyChanged(x => x.IsButtonActive);
        }
    }

    public DefaultViewModel()
    {
        IObservable tbOne = this.WhenAny(x => x.TextOne, x => x.Value).Where(text => !string.IsNullOrEmpty(text));
        IObservable tbTwo = this.WhenAny(x => x.TextTwo, x => x.Value).Where(text => !string.IsNullOrEmpty(text));
        IObservable tbThree = this.WhenAny(x => x.TextThree, x => x.Value).Where(text => !string.IsNullOrEmpty(text));

        var observables = new List> {tbOne, tbTwo, tbThree};
        observables.CombineLatest().Subscribe(x => IsButtonActive = !IsButtonActive);
    }
}
  

Zum Start wird dem ViewModel die Basisklasse ReactiveObject gesetzt. Sie bietet eine fertige Implementierung von INotifyPropertyChanged. Die RaisePropertyChanged-Methode ermöglicht dann das typsichere Infomieren der Änderungen. Das ist für herkömmliche MVVM-Frameworks nichts Neues. Jedoch kann nun mit der WhenAny-Methode jedes Property als IObservable abgefangen werden. Im ViewModel-Konstruktor wird für alle TextBox-Controls ein eigenes IObservable erzeugt. Als Regel wird durch die Where-Methode definiert, dass die Observable-Instanz nur gefeuert werden darf, wenn ein Text enthalten ist. Die Observable-Instanzen werden anschließend in einer Liste gesammelt. Mit der CombineLatest-Methode wird dann definiert, dass gewartet wird, bis alle in der Liste enthaltenen Observables ausgelöst wurden. Ganz gleich, in welcher Reihenfolge dies geschehen ist. Listing 2 demonstriert die Lösung mittels ReactiveUI.

Menü 3 für Windows Phone 7: Live Tile erstellen

In der vorletzten Ausgabe von Silverlight Expertise wurde mit „Tiles in Windows Phone 7.5 Mango“ gezeigt, wie die Tiles einer Windows-Phone-7-App mit Statusinformationen aktualisiert werden können. Ab dem Mango-Update ist noch ein weiteres interessantes Feature zu den Tiles hinzugekommen: Neben dem Standard-Tile einer App (Abb. 1) können weitere Tiles zusätzlich angelegt werden (Abb. 2 und 3).

Abb. 1: Standard Live Tile einer App
Abb. 1: Standard Live Tile einer App
Abb. 2: Beispiel: Neues Live Tile erstellen
Abb. 2: Beispiel: Neues Live Tile erstellen
Abb. 3: Neu erstelltes Live Tile
Abb. 3: Neu erstelltes Live Tile

Sie dienen als Verknüpfung zur eigenen App. So können bestimmte Anforderungen gesondert geöffnet werden oder auch explizite Informationen im Hub anzeigen. Zum Beispiel könnte eine Rezepte-App nun auch beliebige Rezepte direkt vom Hub aus aufrufbar machen. Zu Beginn müssen erst die Informationen des neuen Live Tiles mittels StandardTileData-Instanz definiert werden. Hierbei stehen folgende Properties zur Verfügung: Count, BackgroundImage, BackContent, BackTitle und BackBackgroundImage. Mit der Klasse ShellTile wird dann mit der statischen Create-Methode ein neues Tile erzeugt. Als erster Parameter wird der Pfad zu einem UserControl innerhalb der eigenen App abgefragt. Das UserControl dient als direkte Verknüpfung. Es muss als URI angegeben werden. Der zweite Parameter erhält die soeben angelegte StandardTileData-Instanz. Wenn ein Tile wieder gelöscht werden soll, muss man es von der ShellTile.ActiveTiles-Property beziehen. Die ShellTile-Instanz bietet dann eine Delete-Methode (Listing 3).

Listing 3: Neue Live Tiles unter Windows Phone 7.1 Mango erzeugen

private void BnCreateTileClick(object sender, RoutedEventArgs e)
{
    StandardTileData standardTileData = new StandardTileData
                                            {
                                                Title = textBox1.Text
                                            };

    ShellTile.Create(new Uri("/LiveTileUserControl.xaml?parameter=FromTile", UriKind.Relative), standardTileData);
}

private void bnDeleteTileClick(object sender, RoutedEventArgs e)
{
    ShellTile shellTile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("parameter=FromTile"));

    if (shellTile != null)
    {
        shellTile.Delete();
    }
}
  

Gregor Biswanger ist Microsoft MVP für Client App Dev und arbeitet als Solution Architect und Silverlight-Experte in der Firma impuls Informationsmanagement GmbH in Nürnberg. Seine Schwerpunkte sind die .NET-Architektur, Silverlight und agile Prozesse. Er veröffentlichte vor Kurzem seine DVD mit Videotrainings zum Thema „WPF 4 und Silverlight 4“ bei Addison-Wesley von video2brain. Biswanger ist auch freier Autor, Speaker und Microsoft CLIPler der INdotNET (Ingolstädter .NET Developers Group). Sie erreichen seinen Blog unter www.dotnet-blog.net.
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -