Problèmes de localisation StringFormat dans wpf


112

Dans WPF 3.5SP1, j'utilise la dernière fonctionnalité StringFormat dans DataBindings:

     <TextBlock Text="{Binding Path=Model.SelectedNoteBook.OriginalDate, StringFormat='f'}"
                FontSize="20" TextTrimming="CharacterEllipsis" />

Le problème auquel je suis confronté est que la date est toujours formatée en anglais ... bien que mon système soit en français? Comment puis-je forcer la date à suivre la date du système?


14
3 ans une question hautement cotée mais aucune réponse marquée! Des visages tristes tout autour.
Gusdor

Réponses:


212
// Ensure the current culture passed into bindings is the OS culture.
// By default, WPF uses en-US as the culture, regardless of the system settings.
FrameworkElement.LanguageProperty.OverrideMetadata(
      typeof(FrameworkElement),
      new FrameworkPropertyMetadata(
          XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

À partir de la création d'un assistant internationalisé dans WPF


17
Oui, c'est assez ennuyeux. +1
Szymon Rozga

2
Merci d'avoir résolu mon mal de tête.
Skurmedel

9
Génial. Mais que faire si la culture change pendant le cycle de vie de l'application (par exemple, l'utilisateur peut changer sa culture préférée dans une boîte de dialogue de paramètres). Selon la documentation FrameworkElement.LanguageProperty.OverrideMetadata ne peut pas être appelé plus d'une fois (il lève une exception)
TJKjaer

1
@pengibot Cette solution fonctionne pour moi. J'utilise .net 4 / C # / WPF et je mets le code dans la méthode OnStartup.
Björn

18
Notez que l' élément Run n'hérite pas de FrameworkElement , donc si vous liez des dates, etc. à un Run, vous aurez besoin d'un appel supplémentaire pour typeof (System.Windows.Documents.Run)
Mat Fergusson

90

Définissez l'espace de noms XML suivant:

xmlns:gl="clr-namespace:System.Globalization;assembly=mscorlib"

Maintenant, voici ce correctif fantastique:

<TextBlock Text="{Binding Path=Model.SelectedNoteBook.OriginalDate, StringFormat='f', ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}" FontSize="20"TextTrimming="CharacterEllipsis" />

Je suis bien conscient que ce n'est pas un correctif global et vous en aurez besoin sur chacune de vos liaisons, mais c'est sûrement juste du bon XAML? Pour autant que je sache, la prochaine fois que la liaison sera mise à jour, elle utilisera le correct CultureInfo.CurrentCultureou ce que vous avez fourni.

Cette solution mettra immédiatement à jour vos liaisons avec les valeurs correctes, mais cela semble être beaucoup de code pour quelque chose d'aussi rare et inoffensif.


4
Excellent! Cela a fonctionné à merveille! Je n'ai aucun problème à ajouter cela aux quelques endroits où c'est nécessaire. Btw votre exemple manque un}
Johncl

3
Excellent travail. C'est tellement étrange que WPF utilise l'anglais américain par défaut, par opposition à la culture actuelle.
Kris Adams

12

Je voulais juste ajouter que la réponse de Loraderon fonctionne très bien dans la plupart des cas. Lorsque je mets la ligne de code suivante dans mon App.xaml.cs, les dates de mes TextBlocks sont formatées dans la culture correcte.

FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

Je dis `` la plupart des cas '', par exemple, cela fonctionnera immédiatement:

<TextBlock Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}}" />
--> "16 mei 2013" (this is in Dutch)

... mais lors de l'utilisation de Run dans un TextBlock, le DateTime est formaté dans la culture par défaut.

<TextBlock>
  <Run Text="Datum: " />
  <Run Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}, Mode=OneWay}" />
</TextBlock>
--> "Datum: 16 may 2013" (this is in English, notice the
    name of the month "may" vs. "mei")

Pour que cela fonctionne, j'avais besoin de la réponse de Gusdor , à savoir ajouter ConverterCulture = {x: Static gl: CultureInfo.CurrentCulture} à la liaison.

<TextBlock>
  <Run Text="Datum: " />
  <Run Text="{Binding Path=Date, StringFormat={}{0:d MMMM yyyy}, ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}, Mode=OneWay}" />
</TextBlock>
--> "Datum: 16 mei 2013" (=Dutch)

J'espère que cette réponse supplémentaire sera utile à quelqu'un.


En effet, Run ne dérive pas de FrameworkElement. Vous pouvez essayer de modifier la réponse de loraderon pour répéter son code pour la base de Run (FrameworkContentElement) ainsi que pour FrameworkElement.
Nathan Phillips

Pour ceux qui pourraient se demander: xmlns: gl = "clr-namespace: System.Globalization; assembly = mscorlib"
Igor Meszaros

11

Insérez simplement le raccourci de culture vers la balise de niveau supérieur:

xml:lang="de-DE"

par exemple:

<Window x:Class="MyApp"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xml:lang="de-DE"
    Title="MyApp" Height="309" Width="497" Loaded="Window_Loaded">....</Window>

5
Mais c'est tout aussi mauvais que de supposer que en-US est la culture «correcte». Il devrait plutôt prendre les paramètres de la machine de l'utilisateur.
terme impropre

Merci beaucoup, c'était exactement ce que je cherchais! Si WPF pense que en-EN est la culture appropriée pour n'importe quelle situation, je le peux aussi avec ma propre localisation. Alors que je travaille sur une application de preuve de concept où la vitesse de développement est à l'ordre du jour, il n'y a pas de temps pour jouer avec des dizaines de lignes de code juste pour en obtenir une seule DatePickerpour faire son travail, donc cette solution facile a obtenu me remettre rapidement sur les rails!
M463

meilleure réponse pour mon cas, enfin cherché depuis des lustres :) et bien sûr c'est correct, soit vous supposez que c'est en-US ou c'est de-DE ... les gens ont toujours des problèmes avec des solutions simples -.-
MushyPeas

10

Comme déjà indiqué, XAML utilise par défaut la culture invariante (en-US), et vous pouvez utiliser

FrameworkElement.LanguageProperty.OverrideMetadata(
  typeof(FrameworkElement),
  new FrameworkPropertyMetadata(
      XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

pour définir la culture sur la culture par défaut pour la langue de la culture actuelle. Mais le commentaire est faux; cela n'utilise pas la culture actuelle, car vous ne verrez aucune personnalisation que l'utilisateur aurait pu faire, ce sera toujours la valeur par défaut pour la langue.

Pour utiliser réellement la culture actuelle avec des personnalisations, vous devrez définir le ConverterCultureavec le StringFormat, comme dans

Text="{Binding Day, StringFormat='d', ConverterCulture={x:Static gl:CultureInfo.CurrentCulture}}"

avec le gldéfini comme un espace de noms global dans votre élément racine

xmlns:gl="clr-namespace:System.Globalization;assembly=mscorlib"

Si vous faites cela via du code au lieu de XAML, c'est comme suit:binding.ConverterCulture = System.Globalization.CultureInfo.CurrentCulture;
Metalogic

8

Si vous avez besoin de changer la langue pendant que le programme est en cours d'exécution, vous pouvez simplement changer la propriété Language sur votre élément racine (je ne sais pas si cela a un effet instantané ou si le sous-élément doit être recréé, dans mon cas, cela fonctionne au moins)

element.Language = System.Windows.Markup.XmlLanguage.GetLanguage(culture.IetfLanguageTag);

il réévalue immédiatement mais doit malheureusement être défini pour chaque élément racine (fenêtre) séparé
Firo

6

Le code complet pour basculer la localisation également dans des éléments comme celui <Run />-ci:

Private Shared Sub SetXamlBindingLanguage()

    '' For correct regional settings in WPF (e.g. system decimal / dot or comma) 
    Dim lang = System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(TextElement), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(DefinitionBase), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FixedDocument), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FixedDocumentSequence), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(FlowDocument), New FrameworkPropertyMetadata(lang))
    FrameworkContentElement.LanguageProperty.OverrideMetadata(GetType(TableColumn), New FrameworkPropertyMetadata(lang))
    FrameworkElement.LanguageProperty.OverrideMetadata(GetType(FrameworkElement), New FrameworkPropertyMetadata(lang))

End Sub

0

Si vous souhaitez modifier les informations de culture au moment de l'exécution, vous pouvez utiliser un comportement (voir ci-dessous)

  public class CultureBehavior<TControl> : Behavior<TControl>
    where TControl : FrameworkElement
{
    private readonly IEventAggregator _eventAggregator;
    private readonly Action<CultureInfo> _handler;

    public CultureBehavior()
    {
        _handler = (ci) => this.AssociatedObject.Language = XmlLanguage.GetLanguage(ci.IetfLanguageTag);
        _eventAggregator = IoC.Container.Resolve<IEventAggregator>();
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        _eventAggregator
            .GetEvent<LanguageChangedEvent>()
            .Subscribe(_handler);

        _handler.Invoke(CultureInfo.CurrentCulture);
    }

    protected override void OnDetaching()
    {
        _eventAggregator
            .GetEvent<LanguageChangedEvent>()
            .Unsubscribe(_handler);

        base.OnDetaching();
    }
}

0

Si vous travaillez sur du code plutôt que sur XAML, vous pouvez définir le ConverterCulture comme suit:

binding.ConverterCulture = System.Globalization.CultureInfo.CurrentCulture;

Félicitations à @KZeise pour avoir souligné la différence subtile entre l'utilisation de la définition de culture par défaut et l'utilisation de la définition de culture personnalisée de l'utilisateur.


-3

Utilisez Label (y compris Cultture) et non texblock

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.