WPF Evaluation: Spaß mit der StaticMarkupExtension

Sehr interessant fand ich auch die Möglichkeiten des Einsatzes der x:Static Markup Erweiterung, hier am Beispiel der Konfiguration. Die Konfiguration der Anwendung ist .NET konform in den Settings gespeichert und es wird ein Dialog angeboten, der jeden einzelnen Eintrag zum Ändern anbietet – etwa die URL zum SOAP Web Service des VCR.NET Recording Service. Im Beispiel wird der DataContext des Dialogs direkt an diese Einstellungen gebunden (DataContext=”{x:Static app:Properties.Settings.Default}”). Die einzelnen Formularelemente binden sich dann relativ an die Einzeleintragungen (Text=”{Binding Path=ServerUri, Mode=TwoWay, UpdateSourceTrigger=Explicit}”), wobei ich aber bewußt die explizite Aktualisierung verwende, da bei einem Abbruch keine Veränderungen vorgenommen werden sollen. Das geht in der einfachen Implementierung nur teilweise, dazu gleich mehr.

config.jpg

Ergänzend sieht man im Programmcode des Dialogs, wie diese Aktualisierung auch auf einen Rutsch dynamisch vorgenommen wird, ohne dass jedes Formularelement explizit angesprochen werden muss. Konkret bedeutet das, dass ein neuer Konfigurationseintrag letztlich nur in der XAML mit einem Formularelement eingetragen werden muss um gepflegt zu werden: es ist kein zusätzlicher Programmcode notwendig.

So wie es implementiert ist, funktioniert es allerdings nicht wirklich: an einigen Konfigurationseinträgen hängen Prüfungen (ValidationRule) und nur wenn alle Prüfungen Erfolg melden, kann das Formular gespeichert werden. Bei einer Gesamtprüfung werden aber alle erfolgreichen Eingaben bereits in die Konfiguration übertragen und sind damit zumindest für die weitere Nutzung der Anwendung verändert – auf Platte gespeichert werden kann allerdings nur, wenn alles korrekt eingegeben wurde. Ich habe dem zumindest optisch Rechnung getragen, indem die Abbrechen Schaltfläche deaktiviert wird. Ist aber nur halbherzig, da man den Dialog immer noch über das Kreuzchen rechts oben schliessen kann. Wieder für eine produktive Lösung undenkbar, aber das ist hier erst einmal irrelevant.

Eine zweite Anwendung von x:Static findet man in der Anwendung selbst. Hier wird eine Auflistung (TextFilterTypes[] FilterTypes) aller Alternativen einer .NET Enum angeboten, die in einer Auswahlliste angezeigt werden soll (ItemsSource=”{x:Static app:App.FilterTypes}”). Eine Erweiterung um eine Alternative erfordert erst einmal nur die Veränderung der Enum Definition und die Oberfläche folgt dieser sofort. Dass die Beispielanwendung diese Altenativen über WPF Ressourcen auf Texte abbildet ist für das Prinzp ohne Bedeutung – auch wenn das natürlich heißt, dass man doch zumindest einen weiteren Eintrag in den Ressourcen ergänzen muss.

Viel Spaß

Jochen

WPF Evaluation: Die Datenquelle

WPF ist sehr flexibel, wenn es darum geht, Daten an Oberflächenelemente zu binden. Als Datenquelle für mein kleines Beispiel dient der SOAP Web Service des VCR.NET Recording Service (ich denke aber, dass die folgenden Überlegungen für WCF sehr ähnlich sein werden) und dabei vor allem der Abruf der vollständigen Programmzeitschrift für ein Geräteprofil. Ich verwende hier bewusst die gesamte Programmzeitschrift, da es genau die Aufgabe des Beispielprogramms sein soll, diese geeignet zu filtern.

Wenn man eine Anwendung an eine Web Service bindet, so werden eine Reihe von Proxy Klassen im Projekt erzeugt (Unterverzeichnis Web References). Im Beispiel liefert die entscheidende Methode (GetEPGData) ein Feld mit EPGEvent Instanzen. Die Einträge der Programmzeitschrift sind allerdings zur direkten Darstellung wenig geeignet, enthalten sie doch den Startzeitpunkt in GMT / UTC Notation und statt des Endzeitpunktes die Dauer in Sekunden.

Glücklicherweise werden alle Proxy Klassen als partiellen Klassen (partial class) angelegt, so dass es ein Einfaches ist, diese mit geeigneten Eigenschaften und Methoden zu ergänzen. Im Beispiel wird dies hier gezeigt. Die Klasse EPGEvent bietet nun einen einfachen Zugriff auf Start und Ende in der lokalen Zeitzone und einige Hilfseigenschaften, die zur Variation der Darstellung benötigt werden (etwa meldet IsCurrent ob die Sendung jetzt gerade läuft). Zusätzlich wurden die Klassen zur Programmierung von Aufzeichnungen erweitert. Zu einem Auftrag (VCRJob) können nun einfach neue Aufzeichnungen hinzugefügt werden und eine Aufzeichnung (VCRSchedule) erlaubt eine Pflege der Aufzeichnungsparameter (FirstStart als GMT / UTC und Duration in Minuten) elegant in der lokalen Zeitzone über Start- und Endzeitpunkt.

Interessanter Weise macht der Code in dieser Datei auch einen erheblichen Anteil am Gesamtcode und der Kommunikation mit VCR.NET aus. Für das Laden der Programmzeitschrift wurde ein asynchroner Mechanismus gewählt, der ideal zu den asynchronen dynamischen Werten von WPF (Binding.IsAsync) passt – dazu in einem anderen Artikel. Beim Erzeugen der ProgramGuide Hilfsklasse wird VCR.NET asynchron kontaktiert, ein Abruf der Werte ist erst möglich, wenn eine Antwort bereit steht. Da die Instanz der Hilfsklasse als WPF Ressource angelegt wird (auch dazu an anderer Stelle mehr) wird dieser Vorgang sehr früh beim Starten der Anwendung angeworfen und kann parallel zum Aufbau des Hauptfensters abgearbeitet werden.

Auf technische Details der Implementierung will ich hier nicht eingehen – Thema ist ja WPF. Erwähnt werden sollte allerdings eine wesentliche Unschönheit in dem vorhandenen Code: wenn die SOAP URL des Servers nicht stimmt, so passiert erst einmal gar nichts. Hier muss der Anwender über die Konfiguration eine korrekte Adresse eintragen und die Anwendung neu starten. Für eine produktive Anwendung ein Unding, aber für das Ziel dieser Evaluation völlig ausreichend.

So long

Jochen