Expression Blend

Design Time Data - Alternative zu Expression Blends Sample Data (Teil 1)

Die meisten aktuellen Silverlight oder WPF Projekte sind zum Glück nach MVVM umgesetzt und so erhalten die Views ihre Daten aus den jeweiligen ViewModels. Um dann richtig designen zu können ist es unumgänglich mit Design Time Sample Data zu arbeiten. Denn nur dann ist es wirklich möglich, in Expression Blend oder dem Designer von Visual Studio zu arbeiten, ohne nach jeder Änderung das Projekt bauen und starten zu müssen.

Expression Blend

Design Time Data - Alternative zu Expression Blends Sample Data (Teil 1)

Die meisten aktuellen Silverlight oder WPF Projekte sind zum Glück nach MVVM umgesetzt und so erhalten die Views ihre Daten aus den jeweiligen ViewModels. Um dann richtig designen zu können ist es unumgänglich mit Design Time Sample Data zu arbeiten. Denn nur dann ist es wirklich möglich, in Expression Blend oder dem Designer von Visual Studio zu arbeiten, ohne nach jeder Änderung das Projekt bauen und starten zu müssen. Leider wird das in vielen Projekten unterschätzt und der Weg, um ein Design zu prüfen, führt unweigerlich über das Starten und Navigieren innerhalb der Anwendung (was in den seltensten Fällen schnell geht).

Eine Lösung für dieses Problem bietet Blend von Haus aus an: Sample Data. Diese sollen dem Anwender auf möglichst einfache und schnelle Weise die Möglichkeit geben, zur Designzeit (also entweder in Blend oder dem Visual Studio Designer) die datengebundenen Controls mit Content zu befüllen. In der Theorie (oder bei einfachen bzw. kleinen Projekten) funktioniert dieses Verfahren auch sehr gut. Blend kann beispielsweise aus den ViewModel Klassen Sample Data generieren und legt dafür eigene .xaml Dateien in dem Ordner "SampleData" an. Der große Vorteil ist, dass der Anwender im Idealfall keinen Mehraufwand hat, da Blend auf Basis der public Properties und der Typen automatisch Daten erzeugt. 

So werden z.B. string Properties durch "Lorem ipsum" gefüllt und DateTime Properties mit zufälligen Daten. Selbst komplexe Typen werden nachgebildet:

Dieses Verfahren hat allerdings auch entscheidene Nachteile (gerade in realen Projekten wichtig):

  1. In jedem Projekt mit Sample Data wird ein neuer Ordner inkl. verschiedener .xaml Dateien erzeugt
  2. Man hat ohne weiteres keinen Einfluß auf die erzeugten Daten
  3. Eine einfache Aktualisierung der Daten / Klassenstruktur ist nicht möglich (Diese müssen neu erzeugt werden)

 Eine Idee zu einer Alternative möchte ich daher hier gerne vorstellen: Um vollständige Kontrolle über die Beispieldaten zu erhalten ist es notwendig, diese selber zu erstellen. Um darüberhinaus noch die Möglichkeit des einfachen Refactorings bzw. Aktualisierung zu bekommen, ist die Idee, eine eigene Klasse für die jeweiligen Daten zu erzeugen. Hat man beispielsweise ein ViewModel, so kann man eine neue Klasse von diesem ViewModel ableiten und die entsprechenden Properties mit Daten füllen bzw. sinnvoll initialisieren. 

Original ViewModelSample Data ViewModel

 

 

 

 

 

 

 

 

 

Auf der linken Seite ist das original ViewModel zu sehen, auf der rechte Seite die abgeleitete Klasse mit den Beispieldaten. Dort werden exemplarisch zwei Möglichkeiten verwendet, um die Properties mit Daten zu befüllen: Im Konstruktor oder als Überschreibung der Property.

Wenn man jetzt allerdings die original Klasse refactored und z.B. eine Property umbenennt, so wird das Sample Data ViewModel direkt mit angepasst. Außerdem hat man jetzt die Möglichkeit alle Daten selber zu bestimmen und beispielsweise auch mal lange Namen oder Sonderzeichen auszuprobieren.

Um die neue Klasse im Designer zu verwenden ist lediglich folgende Zeile Code in der View notwendig:

Das Attribut "IsDesignTimeCreatable" muss dabei auf jeden Fall auf "True" stehen, damit die Klasse (und damit auch der parameterlose Konstruktor) durch den Designer aufgerufen wird.

 Einen entscheidenen Nachteil hat dieses Vorgeher jedoch: Wie beim Erzeugen von zusätzlichen .xaml Dateien durch Blend, werden auch hier die Projekte durch weitere Dateien/Klassen "aufgebläht". Wem das egal ist, der braucht jetzt nicht weiterzulesen ;-)

Für alle anderen habe ich noch einen kleinen "Trick", um diese Sample Data Klassen zu verstecken. In der .csproj Datei eines Projektes kann man Abhängigkeiten definieren:

So kann man erreichen, dass die abgeleiteten ViewModels in Visual Studio (und in Blend) hinter den jeweiligen originalen ViewModels "versteckt" werden:

Leider ist mir bisher nur die Möglichkeit bekannt, die Abhängigkeit manuell in der .csproj Datei einzutragen, aber vielleicht gibt es auch dafür Extensions (z.B. ReSharper, VS Commands etc.)?!

In einem zweiten Teil (kommt später) möchte ich noch eine weitere, alternative Idee zu Beispieldaten vorstellen, die genau den 3. Kritikpunkt (zusätzliche Dateien in den Projekten) addressiert.


C#

Visual Studio - Aktuelle Datei im Solution Explorer anzeigen

Wahrscheinlich wird es jeder wissen und mich für total unfähig halten, ABER ich habe heute eine sehr hilfreiche Visual Studio Option kennengelernt:

"Track Active Item in Solution Explorer"

 

C#

Visual Studio - Aktuelle Datei im Solution Explorer anzeigen

Wahrscheinlich wird es jeder wissen und mich für total unfähig halten, ABER ich habe heute eine sehr hilfreiche Visual Studio Option kennengelernt:

"Track Active Item in Solution Explorer"

 

Diese Option bewirkt, dass die gerade bearbeitete Datei im Solution Explorer markiert wird. Auch wenn es eine Datei ist, die sich in einem anderen Projekt befindet, wird der entsprechende Baum aufgeklappt und die Datei markiert. Oft habe ich diese Option durch Visual Studio Extensions aktiviert, aber es geht auch einfach mit Bordmitteln ;-)


XAML

Folien zur Basta Spring 2012

Hier meine Folien und das Code-Beispiel zum Vortrag "VisualStateManager: Schnittstelle zwischen Entwickler und Designer" auf der Basta Spring 2012 in Darmstadt. Dazu die in der Session erwähnten Folien zu "Steuerelemententwicklung mit WPF, Silverlight und Windows Phone 7" (in dessen Kontext der gestrige Vortrag stand) und die Folien von der GUI & DESIGN im Dezemeber 2011 mit dem Titel "Die 8 gängigen Fehler in der Implementierung von User Interface mit WPF und Silverlight".

 

XAML

Folien zur Basta Spring 2012

Hier meine Folien und das Code-Beispiel zum Vortrag "VisualStateManager: Schnittstelle zwischen Entwickler und Designer" auf der Basta Spring 2012 in Darmstadt. Dazu die in der Session erwähnten Folien zu "Steuerelemententwicklung mit WPF, Silverlight und Windows Phone 7" (in dessen Kontext der gestrige Vortrag stand) und die Folien von der GUI & DESIGN im Dezemeber 2011 mit dem Titel "Die 8 gängigen Fehler in der Implementierung von User Interface mit WPF und Silverlight".

 


Silverlight

Dinge, die man mit einem Rebuild erreichen kann

Hiermit möchte ich gerne eine neue Kategorie eröffnen: Nervige Zeitfresser, die man einfach durch ein Rebuild lösen kann ;-) Diese Liste soll eine dezente Erinnerung an alle verzweifelte Entwickler da draußen sein, ab und zu einfach mal ein Rebuild zu machen.

Silverlight

Dinge, die man mit einem Rebuild erreichen kann

Hiermit möchte ich gerne eine neue Kategorie eröffnen: Nervige Zeitfresser, die man einfach durch ein Rebuild lösen kann ;-) Diese Liste soll eine dezente Erinnerung an alle verzweifelte Entwickler da draußen sein, ab und zu einfach mal ein Rebuild zu machen. Manche Fehler lösen sich dadurch vielleicht in Luft auf: - Implizite Styles in Silverlight: Nachdem ich gefühlte 3h den Fehler in allen möglichen Resourcen und Verknüfungen gesucht habe, half ein einfacher Rebuild und 'Tataa', alle ScrollViewer (und alle anderen Controls) zogen sich auf ein mal den impliziten Style, den ich definiert hatte! ... to be continued ... PS: Falls ihr auch ähnliche Beispiele habt, lasst es mich wissen, ich werde die Liste dann aktualisieren.


Silverlight

IsEnabled überschreiben

Ausgangslage:

Ich habe ein CustomControl (z.B. abgeleitet von ContentControl), dass aus mehreren weiteren Elementen (z.B. einem Button) besteht.

Ziel:

Wenn ich bei meinem CustomControl "IsEnabled = false" setze, dann soll nur der Inhalt des Controls disabled werden, nicht jedoch das gesamte Control und damit auch der Button.

Silverlight

IsEnabled überschreiben

Ausgangslage:

Ich habe ein CustomControl (z.B. abgeleitet von ContentControl), dass aus mehreren weiteren Elementen (z.B. einem Button) besteht.

Ziel:

Wenn ich bei meinem CustomControl "IsEnabled = false" setze, dann soll nur der Inhalt des Controls disabled werden, nicht jedoch das gesamte Control und damit auch der Button.

Problem:

Die Property IsEnabled wird an die Kinder vererbt (bzw. die Kinder erben vom Parent) und damit wird auch automatisch der Button im Template disabled. Es gibt zwar ein IsEnabledChanged Event, allerdings kann man dort nicht so etwas sagen wie "IsHandled = true".

Lösung:

Es gibt allerdings einen kleinen Trick und zwar kann man wie folgt die DependencyProperty überschreiben: Wichtig dabei ist das "new" Keyword bei der DependencyProperty und dem Property Wrapper. Außerdem reicht es nicht, nur die Property zu überschreiben, es muss die komplette DependencyProperty sein.


Expression Blend

Mögliche Lösung, wenn Expression Blend Sample Data nicht angezeigt werden...

Ein kleiner Tipp, der mich gerade viel Zeit gekostet hat :-( Wenn SampleData in Blend zur Design-Time angezeigt werden, nicht aber zur Laufzeit, kann sich ein Blick in die XAML-Datei der SampleData im Ordner "SampleData" lohnen. Denn wenn dort Fehler auftreten, kann trotzdem fehlerlos kompiliert werden. Gravierend kann das z.B. der Fall sein, wenn ein Feld-Typ "Image" benutzt wird, der generierte Pfad aber nicht mehr auf eine vorhandene Datei zeigt, weil die Grafik gelöscht wurde beispielsweise...

Expression Blend

Mögliche Lösung, wenn Expression Blend Sample Data nicht angezeigt werden...

Ein kleiner Tipp, der mich gerade viel Zeit gekostet hat :-( Wenn SampleData in Blend zur Design-Time angezeigt werden, nicht aber zur Laufzeit, kann sich ein Blick in die XAML-Datei der SampleData im Ordner "SampleData" lohnen. Denn wenn dort Fehler auftreten, kann trotzdem fehlerlos kompiliert werden. Gravierend kann das z.B. der Fall sein, wenn ein Feld-Typ "Image" benutzt wird, der generierte Pfad aber nicht mehr auf eine vorhandene Datei zeigt, weil die Grafik gelöscht wurde beispielsweise...


WPF

CornerRadius eines Borders animieren

Expression Blend generiert bei dem Versuch einen CornerRadius in einem Stordboard zu animieren falschen Code, der sofort in einer Exception "Input string was not in a correct format." resultiert. Fehler-Details und Abhilfe unter https://connect.microsoft.com/Expression/feedback/details/694672/xaml-ge...

WPF

CornerRadius eines Borders animieren

Expression Blend generiert bei dem Versuch einen CornerRadius in einem Stordboard zu animieren falschen Code, der sofort in einer Exception "Input string was not in a correct format." resultiert. Fehler-Details und Abhilfe unter https://connect.microsoft.com/Expression/feedback/details/694672/xaml-ge...


Expression Blend

Unterschiedliche Rundung mit und ohne Stroke

Manchmal gibt es bei abgerundeten Ecken ganz leichte, aber störende Blitzer, denen selbst SnapToDevicePixel nichts anhaben kann. Das liegt daran, dass die Rundung mit und ohne Stroke ein kleines bisschen anders ausfällt... Ohne Stroke auf dem dunklen Hintergrund-Element: Einfach nur gesetzter Stroke auf dem dunklen Hintergrund-Element:

Expression Blend

Unterschiedliche Rundung mit und ohne Stroke

Manchmal gibt es bei abgerundeten Ecken ganz leichte, aber störende Blitzer, denen selbst SnapToDevicePixel nichts anhaben kann. Das liegt daran, dass die Rundung mit und ohne Stroke ein kleines bisschen anders ausfällt... Ohne Stroke auf dem dunklen Hintergrund-Element: Einfach nur gesetzter Stroke auf dem dunklen Hintergrund-Element:


Silverlight

Copy&Paste FAIL: Doppelte Setter im Style

Vielleicht ist es dem einen oder anderen schon passiert: Durch einfaches Kopieren innerhalb von Styles hat man auf ein mal doppelte Setter. Wenn die dann auch nicht direkt untereinander stehen (was der Regelfall sein sollte), kann die Fehlersuche sehr frustrierend sein.

Silverlight

Copy&Paste FAIL: Doppelte Setter im Style

Vielleicht ist es dem einen oder anderen schon passiert: Durch einfaches Kopieren innerhalb von Styles hat man auf ein mal doppelte Setter. Wenn die dann auch nicht direkt untereinander stehen (was der Regelfall sein sollte), kann die Fehlersuche sehr frustrierend sein. Ich möchte daher kurz die Problematik schildern, um so vielleicht den ein oder anderen Frust-Moment zu vermeiden ;-) Die Ausgangslage soll folgendes Bild verdeutlichen: Wie man sieht, lässt es WPF (und auch Silverlight) zu, doppelte Setter im Style zu verwenden, ohne eine Fehlermeldung zur Design- / Laufzeit zu schmeißen. Das Verhalten ist dadurch allerdings nicht mehr eindeutig korrekt. Zur Laufzeit (und im Designer) überschreibt der letzte Setter den Wert der Property. Wenn man nun aber z.B. über Blend die Property ändert, so ändert Blend den Wert des ersten Setters, was augenscheinlich keine Auswirkungen auf das Ergebnis hat. Die Verwirrung ist umso größer, wenn in diesem Fall über Blend eine Resource an die Property gebunden wird. Blend zeigt nun einen gelben Rahmen um die Property (was bedeutet, dass diese gebunden ist), allerdings hat das keine Auswirkungen auf das Ergebnis, weder im Designer, noch zur Laufzeit. FAZIT: Steht man mal wieder vor dem Rätsel, warum ein Binding in einem Style nicht funktioniert, einfach mal im XAML Code runterscrollen und überprüfen, ob es einen doppelten Setter gibt ;-) UPDATE: In Silverlight bekommt man zumindest eine Fehlermeldung in Blend, wenn man versucht den Style erneut zu öffnen. Allerdings lässt sich das Projekt trotzdem kompilieren und ausführen (mit dem gleichen Ergebnis, wie oben beschrieben).


Silverlight

Blendable SharedResourceDictionary

Die Idee und Implementierung eines SharedResourceDictionary ist schon einige Tage alt und von Christian Moser auch gut umgesetzt worden (siehe hier http://www.wpftutorial.net/MergedDictionaryPerformance.html). Dennoch hat bisher keiner der Kommentatoren oder der Autor selbst eine Antwort darauf geliefert, wie man das SharedResourceDictionary auch in Blend nutzbar machen kann.

Silverlight

Blendable SharedResourceDictionary

Die Idee und Implementierung eines SharedResourceDictionary ist schon einige Tage alt und von Christian Moser auch gut umgesetzt worden (siehe hier http://www.wpftutorial.net/MergedDictionaryPerformance.html). Dennoch hat bisher keiner der Kommentatoren oder der Autor selbst eine Antwort darauf geliefert, wie man das SharedResourceDictionary auch in Blend nutzbar machen kann. Die aktuelle Implementierung des SharedResourceDictionary wirft zur Designzeit von Blend entsprechende Fehler, auch wenn diese nur sichtbar werden wenn man sich aus dem Visual Studio heraus an Blend attached und debugged. Diese Fehler führen dazu, dass keine der über SharedResourceDictionary definierten Ressourcen in Blend zur Verfügung steht. Die Lösung des Problem ist jedoch sehr simpel. Die Verwendung wird von Christian Moser so beispielhaft erläutert:

<ResourceDictionary.MergedDictionaries>
   <SharedResourceDictionary Source="/MyControlLibrary;component/Themes/Brushes.xaml"  />
</ResourceDictionary.MergedDictionaries>

Hierbei fällt auf, dass nur das ResourceDictionary in der Collection der MergedDictionaries ein SharedResourceDictionary ist und genau hier liegt auch das Problem. Um die Struktur sauber zu nutzen und damit auch in Blend nutzbar zu machen, muss das ResourceDictionary, welches eine MergedDictionaries Collection beinhaltet, ebenfalls durch ein SharedResourceDictionary ersetzt werden:

<SharedResourceDictionary>
   <SharedResourceDictionary.MergedDictionaries>
      <SharedResourceDictionary Source="/MyControlLibrary;component/Themes/Brushes.xaml"  />
   </SharedResourceDictionary.MergedDictionaries>
</SharedResourceDictionary>