web-dev-qa-db-fra.com

WPF XAML StringFormat DateTime: sortie dans une mauvaise culture?

J'ai des problèmes avec la sortie d'une valeur DateTime. La culture actuelle de mon ordinateur est définie sur de-AT (Autriche).

Le code suivant

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

a pour résultat que s1 et s2 ont tous deux la valeur correcte de "30.06.2009".

Mais lorsque vous utilisez le même format en XAML

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

la sortie est "30/06/2009". Il semble que le XAML StringFormat ignore les paramètres de culture actuels. Cela se produit sur Vista et XP.

Je ne veux pas spécifier un format personnalisé, car la sortie doit être formatée dans le paramètre de culture préféré de l'utilisateur.

Quelqu'un avec le même problème? Est-ce un bug dans WPF?

61
Christian Hubmann
42
loraderon

Pour appliquer la solution mentionnée sur http://tinyurl.com/b2jegna , procédez comme suit:

(1) Ajoutez un gestionnaire d'événements de démarrage à la classe Application dans app.xaml:

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

(2) Ajoutez la fonction de gestionnaire:

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

Les chaînes WPF doivent ensuite être formatées correctement en fonction de la culture.

14
Stephen Holt

A écrit il y a quelque temps sur mon blog:

Cela vous expliquera comment faire en sorte que WPF utilise la bonne culture:

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

Cela changera la culture WPF à la volée lorsque vous modifiez les paramètres dans le panneau de configuration:

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

10
Nir

Si vous souhaitez une langue particulière, vous pouvez la définir sur l'élément de niveau supérieur à l'aide de xml:lang.

Par exemple:

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

Je sais que c'est une question vieillissante mais cela a toujours fonctionné pour moi et partager les connaissances est une bonne chose. Étant donné que mes applications changent toujours de langue à la volée, FrameworkElement.LanguageProperty.OverrideMetadata ne fonctionne qu'une seule fois et ce n'est pas bon pour moi, alors voici:

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

où (ceci) est la fenêtre principale, en fait, vous devez le faire dans tous les rootelements (Windows). Là, vous allez assez simple.

3
Nemesis

vous pouvez utiliser un IValueConverter (qui prend un paramètre de culture) et formater la valeur comme vous le souhaitez, quelque chose que j'aime est ce convertisseur nullable par 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

}

voici le original

1
almog.ori