WPF XAML StringFormat DateTime: Output in wrong culture?

C#WpfXamlDatetime

C# Problem Overview


I'm having some trouble with the output of a DateTime value. My computer's current culture is set to de-AT (Austria).

The following code

string s1 = DateTime.Now.ToString("d");
string s2 = string.Format("{0:d}", DateTime.Now);

results in s1 and s2 both having the correct value of "30.06.2009".

But when using the same format in XAML

    <TextBlock Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat=d}"/>

the output is `"6/30/2009". It seems the XAML StringFormat ignores the current culture settings. This happens on both Vista and XP.

I don't want to specify a custom format, because the output should be formatted in the user's preferred culture setting.

Anybody with the same problem? Is this a bug in WPF?

C# Solutions


Solution 1 - C#

Solution 2 - C#

To apply the solution mentioned at http://tinyurl.com/b2jegna do the following:

(1) Add a Startup event handler to the Application class in app.xaml:

<Application x:Class="MyApp"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ...
    Startup="ApplicationStartup">

(2) Add the handler function:

private void ApplicationStartup(object sender, StartupEventArgs e)
{
    FrameworkElement.LanguageProperty.OverrideMetadata(
        typeof(FrameworkElement),
        new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
}

WPF strings should then be formatted correctly according to culture.

Solution 3 - C#

Wrote about it some time ago on my blog:

This will tell you how to get WPF to use the right culture:

http://www.nbdtech.com/blog/archive/2009/02/22/wpf-data-binding-cheat-sheet-update-the-internationalization-fix.aspx

This will change the WPF culture on the fly when you modify the settings in the control panel:

http://www.nbdtech.com/blog/archive/2009/03/18/getting-a-wpf-application-to-pick-up-the-correct-regional.aspx

Solution 4 - C#

If you want one particular language, you can set it on the top level element using xml:lang.

For example:

<Window xml:lang="de-AT">
...
</Window>

Solution 5 - C#

I Know that this is an aging question but this has always worked for me and sharing knowledge is a good thing. Since my apps always change language on the fly, the FrameworkElement.LanguageProperty.OverrideMetadata only works once and its no good for me, so behold:

this.Language = System.Windows.Markup.XmlLanguage.GetLanguage(ActiveLanguage.CultureInfo.IetfLanguageTag);

where (this) is the MainWindow, actually you have to do it in all rootelements (Windows). There you go simple enough.

Solution 6 - C#

you could use a IValueConverter (which takes in a culture parameter) and format the value as you wish, something I like is this nullable converter by Matt Hamilton

class NullableDateTimeConverter : ValidationRule, IValueConverter
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
    if (value == null || value.ToString().Trim().Length == 0) return null;

    return new ValidationResult( 
        ConvertBack(value, typeof(DateTime?), null, cultureInfo) != DependencyProperty.UnsetValue,
        "Please enter a valid date, or leave this value blank");
}

#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value == null) return "";
    DateTime? dt = value as DateTime?;
    if (dt.HasValue)
    {
        return parameter == null ? dt.Value.ToString() : dt.Value.ToString(parameter.ToString());
    }
    return ""; 
} 

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value == null || value.ToString().Trim().Length == 0) return null;
    string s = value.ToString();

    if (s.CompareTo("today") == 0) return DateTime.Today;
    if (s.CompareTo("now") == 0) return DateTime.Now;
    if (s.CompareTo("yesterday") == 0) return DateTime.Today.AddDays(-1);
    if (s.CompareTo("tomorrow") == 0) return DateTime.Today.AddDays(1);

    DateTime dt; 
    if (DateTime.TryParse(value.ToString(), out dt)) return dt; 

    return DependencyProperty.UnsetValue; 
}  
#endregion

}

heres the original

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChristian HubmannView Question on Stackoverflow
Solution 1 - C#loraderonView Answer on Stackoverflow
Solution 2 - C#Stephen HoltView Answer on Stackoverflow
Solution 3 - C#NirView Answer on Stackoverflow
Solution 4 - C#DomyseeView Answer on Stackoverflow
Solution 5 - C#NemesisView Answer on Stackoverflow
Solution 6 - C#almog.oriView Answer on Stackoverflow