XAML ContentStringFormat
Eine der Neuerungen im ServicePack 1 des Framework 3.5 ist die Möglichkeit, Zahlen direkt im XAML Code zu formatieren. In der Vergangenheit ging dies nur über Converter, die man im C# oder VB Code programmieren musste. Converter sind dabei ein sehr mächtiges Werkzeug, da man mit ihnen prinzipiell alle Werte und alle Typen konvertieren kann. Sie können einen boolschen Wert in eine Farbe konvertieren oder Zeichenketten auf vielerlei Arten manipulieren. Möchte man aber nur die Darstellung von Zahlen ändern, sind Converter inzwischen überflüssig, da diese Aufgabe durch ein StringFormat erledigt werden kann. Da ein StringFormat auch in Verbindung mit Databinding funktioniert, ist es ideal, um die Darstellung von Zahlenwerten optisch aufzuwerten.
Mit dem folgenden Code wird das Feld price vom Typ double an eine DataGrid Spalte gebunden. Eine ähnliche Anbindung wäre aber auch im einem TextField-Steuerelement möglich. Obwohl diese Anweisung perfekt funktioniert, lässt die Ausgabe doch etwas zu wünschen übrig, wie die Abbildung zeigt.
<dg:DataGridTextColumn Header="Price"
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False" Binding="{Binding price}">
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False" Binding="{Binding price}">

Schon durch Anhängen der Formatierung
StringFormat=F2 erhalten alle Zahlen zwei
Nachkommastellen. Dabei gehen aber keine
Informationen verloren. Lediglich die Darstellung
wird angepasst.
<dg:DataGridTextColumn Header="Price"
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False" Binding="{Binding price,StringFormat=F2}">
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False" Binding="{Binding price,StringFormat=F2}">

<dg:DataGridTextColumn Header="Price"
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False" Binding="{Binding price}">
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False" Binding="{Binding price}">
Möchte man hingegen auch Tausender-Trennzeichen
darstellen, muss man sich einer anderen
Formatierung bedienen, nämlich StringFormat=N2.
<dg:DataGridTextColumn Header="Price"
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False" Binding="{Binding price,StringFormat=N2 }" >
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False" Binding="{Binding price,StringFormat=N2 }" >

Die Trennzeichen sind jetzt alle dort, wo sie
hingehören, leider sind sie, zumindest für
deutschsprachige Systeme, nicht die Richtigen. Man
muss der Umwandlung auch noch die für die
Konvertierung zu benutzende Kultur mitteilen
<dg:DataGridTextColumn Header="Price"
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False"
Binding="{Binding price, ConverterCulture='de-DE', StringFormat=N2 }" >
CellStyle="{StaticResource RightAlignedCellStyle}"
Width="100*" IsReadOnly="False"
Binding="{Binding price, ConverterCulture='de-DE', StringFormat=N2 }" >
Jetzt erhält man endlich eine korrekte Ausgabe.
Eine Converter-Methode musste tatsächlich nicht
geschrieben werden.

Dieser Lösungsweg ist natürlich mit Vorsicht zu
geniessen, da jetzt die Kultur und damit auch das
Zahlenformat fest vorgegeben sind. Sollte die
Anwendung auch in anderen Kulturen zum Einsatz
kommen, könnte die Formatierung die Anwender
stören, da sie sich nicht automatisch den
Landeseinstellungen anpasst.
Auch dieses Problem kann gelöst werden, allerdings ist es nicht mehr im XAML-Code machbar. Möchten Sie für die gesamte Anwendung die Kultur festlegen, so geht das am besten im statischen Konstuktor der Application.
Auch dieses Problem kann gelöst werden, allerdings ist es nicht mehr im XAML-Code machbar. Möchten Sie für die gesamte Anwendung die Kultur festlegen, so geht das am besten im statischen Konstuktor der Application.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Windows.Markup;
using System.Globalization;
namespace DataGridApplication
{
public partial class App : Application
{
static App()
{
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage
(CultureInfo.CurrentCulture.IetfLanguageTag)));
}
}
}
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Windows.Markup;
using System.Globalization;
namespace DataGridApplication
{
public partial class App : Application
{
static App()
{
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage
(CultureInfo.CurrentCulture.IetfLanguageTag)));
}
}
}
Mit dieser Anweisung wird die Sprache der Anwendung
der im Betriebssystem eingestellten Kultur
angepasst. Der Parameter ConverterCulture='de-DE'
im Binding ist jetzt nicht mehr nötig.
Referenzen und weiterführende Informationen.
http://blogs.msdn.com/llobo/archive/2008/05/19/wpf-3-5-sp1-feature-stringformat.aspx
http://serialseb.blogspot.com/2007/04/wpf-tips-1-have-all-your-dates-times.html
Referenzen und weiterführende Informationen.
http://blogs.msdn.com/llobo/archive/2008/05/19/wpf-3-5-sp1-feature-stringformat.aspx
http://serialseb.blogspot.com/2007/04/wpf-tips-1-have-all-your-dates-times.html