Silverlight Tipp der Woche: ConditionalConverter

by St. Lange 26. August 2010 18:15

In diesem Tipp geht es um das Umschalten zwischen einer Debug- und Release-Ansicht im XAML Designer.

Zusammenfassung

Während man im Code mit #if DEBUG zwischen Debug- und Release-Build unterscheiden kann, gibt es etwas Vergleichbares in XAML nicht. Mit Hilfe eines geeigneten Value Converters kann jedoch Abhilfe geschaffen werden.

Beschreibung

Mit dem #if pragma im Quellcode zwischen verschiedenen Builds zu unterscheiden hat wohl jeder Entwickler schon einmal gemacht. Diese Möglichkeit fehlt mir in XAML, da ich beispielsweise bei komplexeren Layouts während der Entwurfsphase gerne mal bestimmte Bereiche unterschiedlich einfärbe. So kann man viel besser erkennen, ob Margins, Paddings etc. stimmen. Ärgerlich dabei ist, dass man so ein buntes Layout zumindest nicht jedem Kunden zeigen kann und es schön wäre, dieses "Debug Layout" im Release-Build einfach abzuschalten zu können.

Natürlich kann man das mit etwas C#-Code einfach hinbekommen, aber eigentlich will ich die Unterschiede der Builds bereits im Designer sehen. Mit Hilfe des Value Converters ConditionalConverter kann man das erreichen. Das folgende XAML-Fragment zeigt exemplarisch ein Grid, welches im Debug-Build rot und im Release-Build blau ist. Natürlich auch zur Laufzeit, aber vor allem im XAML Designer . Durch den Wechsel des Builds in Visual Studio verändert sich die Anzeige des Designs entsprechend:

<Grid Background="{Binding Converter={StaticResource ConditionalConverter}, ConverterParameter='Red|Blue'}"/>

Der ConditionalConverter liefert je nach Build den ersten oder den zweiten Teil des Parameter-Strings zurück. Das funktioniert natürlich auch mit Zahlen, Texten, Margins etc. Zwar liefert der Converter immer nur Strings, aber diese werden beim Zuweisen an die Property von deren Type Converter entsprechend in den richtigen Typ umgewandelt. Wie das in XAML üblich ist.

Auffällig ist, dass das Binding keinen Path hat. Er wird jedoch auch nicht benötigt, denn das Ergebnis hängt nur von ConverterParameter ab. Die Implementierung ist relativ einfach:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
  string result = null;
  if (parameter is string)
  {
    var param = ((string)parameter).Split('|');
 
#if DEBUG
    result = param[0];
#else
    if (param.Length >= 2)
      result = param[1];
#endif
  }
 
  // "x:Null" represents the markup extension "{x:Null}".
  if (result == "x:Null")
    result = null;
 
  return result;
}

Das Binding wird zur Designzeit allerdings nur dann ausgeführt, wenn die Property DataContext des Target Objekts und die Source-Property des Bindings nicht beide Null sind, denn in diesem Fall wird der Value Converter gar nicht erst aufgerufen. Sollte dies so sein, kann man die Source-Property im Binding einfach auf irgendeinen Wert setzen, denn da der Path nicht definiert ist, wird sie nicht verwendet. Sie darf nur nicht Null sein:

<Grid Background="{Binding Converter={StaticResource ConditionalConverter},
    Source=xyz,
    ConverterParameter='Red|Blue'}"/>

So ist Source nicht mehr Null und das Binding funktioniert.

Man muss noch beachten, mit dem ConditionalConverter keine Properties zu setzen, die eigentlich durch einen Style gesetzt werden sollten. Das Binding hat Vorrang und der Style kommt nicht zur Anwendung.

Eine weitere theoretische Möglichkeit wäre es, den ConditionalConverter in einem Style zu verwenden, z.B. so:

<Style TargetType="Border">
  <Setter Property="Background"
      Value="{Binding Source=_, ConverterParameter='#FF0000|#00FF00',
      Converter={StaticResource ConditionalConverter}}"/>
</Style>

Das funktioniert aber nicht. Während es in WPF durchaus üblich ist Bindings in Styles zu verwenden, ist diese Funktionalität in Silverlight leider noch nicht implementiert. (Genauer gesagt ist sie bisher nur im Designer implementiert. Das Binding im Style funktioniert bei Silverlight zur Designzeit; wenn man aber die Anwendung startet, gibt es eine Fehlermeldung.)

Expression Blend

In Blend funktioniert das Ganze im Prinzip genauso, allerdings muss hier beachtet werden, dass Blend aktuell ausschließlich Debug-Builds erzeugen kann. Wenn man also in Blend die Release-Ansicht betrachten möchte, muss man vorübergehend die Implementierung von ConditionalConverter ändern. Es reicht, einfach Underscore an #if DEBUG anzufügen und damit die Abfrage umzudrehen.

Code-Beispiel

Zum direkten Ausprobieren gibt es hier noch ein Beispiel: Die MainPage.xaml im Designer öffnen und dann zwischen Debug- und Release-Build hin- und herschalten. Vorher beide Builds einmal compilieren.

ConditionalConverter.zip (16 kB)

Hier geht's zum nächsten Tipp.

 
kick it on dotnet-kicks.de

Tags:

Silverlight

Comments are closed

Powered by BlogEngine.NET 1.6.1.0 - Impressum