web-dev-qa-db-fra.com

StringFormat Problèmes de localisation dans wpf

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 ... alors que mon système est en français? Comment puis-je forcer la date à suivre la date du système?

102
jonathan
// 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)));

De Création d'un Wizard internationalisé dans WPF

192
loraderon

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 que vous en aurez besoin sur chacune de vos liaisons, mais c'est sûrement du bon XAML? Autant que je sache, la prochaine fois que la liaison sera mise à jour, elle utilisera le CultureInfo.CurrentCulture correct ou ce que vous avez fourni.

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

80
Gusdor

Il suffit d'insérer 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>
10
Gerrit Horeis

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 appropriée.

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 lorsque vous utilisez Run dans un TextBlock, 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.

8
Daniël Teunkens

Si vous devez changer la langue pendant l'exécution du programme, vous pouvez simplement changer la propriété Language de 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);
8
Peter

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. ceci n'utilise pas la culture actuelle, car vous ne verrez aucune personnalisation que l'utilisateur aurait pu effectuer, ce sera toujours la valeur par défaut pour la langue. 

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

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

avec gldefined en tant qu'espace de nom global dans votre élément racine

xmlns:gl="clr-namespace:System.Globalization;Assembly=mscorlib"
7
KZeise

Le code complet pour changer la localisation également dans des éléments tels que <Run /> est le suivant:

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
5
habakuk

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
user3173620

Si vous travaillez sur du code plutôt que sur XAML, vous pouvez définir 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.

0
Metalogic