Utilisez CultureInfo.CurrentCulture « réel » dans WPF Reliure, non CultureInfo de IetfLanguageTag

StackOverflow https://stackoverflow.com/questions/5831455

Question

Dans mon cas:

J'ai un TextBlock La liaison à une propriété de type DateTime. Je veux qu'il soit affiché comme les paramètres régionaux de l'utilisateur dit.

<TextBlock Text="{Binding Date, StringFormat={}{0:d}}" />

Je suis en train de propriété Langue comme WPF XAML Liaisons et CurrentCulture Affichage dit:

this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag);

Mais avec cette ligne de code affiche simplement le texte comme format par défaut de CultureInfo avec IetfLanguageTag de CurrentCulture dit, non pas comme la valeur effective sélectionnée dans les paramètres de la région de systèmes dit:

(par exemple. De "de-DE" dd.MM.yyyy est utilisé au lieu d'sélectionné aaaa-mm-jj )

Les paramètres régionaux: non la valeur par défaut, mais yyy-MM-dd est utilisé

Y at-il un moyen utilise la liaison au format correct sans définir ConverterCulture sur chaque liaison?

Dans le code

string.Format("{0:d}",Date);

utilise les bons réglages de la culture.

modifier

une autre façon qui ne fonctionne pas comme on le souhaite (comme this.Language = ... fait):

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

et

<Binding Source="{x:Static glob:CultureInfo.CurrentCulture}" 
 Path="IetfLanguageTag" 
 ConverterCulture="{x:Static glob:CultureInfo.InvariantCulture}" />
Était-ce utile?

La solution

Vous pouvez créer une sous-classe de la liaison (par exemple CultureAwareBinding) qui fixe le ConverterCulture automatiquement à la culture actuelle lors de sa création.

Il est pas une solution parfaite, mais il est probablement le seul, car avec effet rétroactif forçant liaison à respecter la culture pourrait briser autre code WPF qui dépend de ce comportement.

Laissez-moi savoir si vous avez besoin d'aide!

Autres conseils

Ceci est une extension de réponse de akzent. Ils ont proposé que nous devrions créer une sous-classe de la classe de reliure et de définir le ConverterCulture à CurrentCulture. Même si la réponse est très simple, je me sens que certaines personnes peuvent ne pas être très à l'aise la mise en œuvre, donc je partage la version du code de la réponse de akzent avec un exemple de la façon de l'utiliser dans XAML.

using System;
using System.Globalization;
using System.Windows.Data;

namespace MyWpfLibrary
{
    public class CultureAwareBinding : Binding
    {
        public CultureAwareBinding()
        {
            ConverterCulture = CultureInfo.CurrentCulture;
        }
    }
}

Exemple de l'utiliser dans XAML

1) Vous devez importer votre espace de noms dans votre fichier XAML:

<Page
    ...
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:myWpfLib="clr-namespace:MyWpfLibrary;assembly=<assembly_name>"
    ...
>

2) l'utilisation réelle du monde du CultureAwareBinding

<Textblock Text="{myWpfLib:CultureAwareBinding Path=Salary, Source=Contact, StringFormat={}{0:C}}" />

Mettre la ligne de code suivante, avant toute interface utilisateur est initialisé. Cela a fonctionné pour moi.

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

(et supprimer tous les paramètres de la culture explicite)

Votre deuxième tentative était proche, et m'a conduit à une solution qui fonctionne pour moi.

Le problème avec le réglage de la ConverterCulture est qu'il est utilisé que lorsque vous avez un convertisseur. Donc, il suffit de créer simple StringFormatConverter qui prend le format comme paramètre:

public sealed class StringFormatConverter : IValueConverter
{
    private static readonly StringFormatConverter instance = new StringFormatConverter();
    public static StringFormatConverter Instance
    {
        get
        {
            return instance;
        }
    }

    private StringFormatConverter()
    {
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return string.Format(culture, (string)parameter, value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Ensuite, vous pouvez ajuster vos fixations (en supposant que vous avez importé l'espace de noms du convertisseur comme « mon »)

<TextBlock Text="{Binding Date, Converter={x:Static my:StringFormatConverter.Instance}, ConverterCulture={x:Static glob:CultureInfo.CurrentCulture}, ConverterParameter={}{0:d}}" />

J'utilise ce code avec des résultats appropriés à mes besoins. Espérons que cela pourrait comble votre :-)! Peut-être vous lancer mieux une exception si ne peut pas « TryParse ». Jusqu'à vous.

public sealed class CurrentCultureDoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((double)value).ToString((string)parameter ?? "0.######", CultureInfo.CurrentCulture);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        double result;
        if (Double.TryParse(value as string, NumberStyles.Number, CultureInfo.CurrentCulture, out result))
        {
            return result;
        }

        throw new FormatException("Unable to convert value:" + value);
        // return value;
    }
}

Utilisation:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:simulatorUi="clr-namespace:SimulatorUi"
        xmlns:Converter="clr-namespace:HQ.Wpf.Util.Converter;assembly=WpfUtil" x:Class="SimulatorUi.DlgTest"
        Title="DlgTest" Height="300" Width="300">
    <Window.DataContext>
        <simulatorUi:DlgTestModel/>
    </Window.DataContext>

    <Window.Resources>
        <Converter:CurrentCultureDoubleConverter x:Key="CurrentCultureDoubleConverter"/>
    </Window.Resources>

    <Grid>
        <TextBox Text="{Binding DoubleVal, Converter={StaticResource CurrentCultureDoubleConverter}}"/>
    </Grid>
</Window>

Je suis venu avec un hack / solution de contournement qui évite la mise à jour toutes vos fixations. Ajoutez ce code au constructeur de la fenêtre principale.

XmlLanguage language = XmlLanguage.GetLanguage("My-Language");
typeof(XmlLanguage).GetField("_compatibleCulture", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(language, CultureInfo.CurrentCulture);
this.Language = language;

Depuis qu'il utilise la réflexion il n'y a aucune garantie que cela fonctionnera à l'avenir, mais pour l'instant il ne (.NET 4.6).

Nous pouvons créer un convertisseur DateTime en utilisant le IValueConverter

[ValueConversion(typeof(DateTime), typeof(String))]
    class DateTimeToLocalConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is DateTime)) return "Invalid DateTime";
            DateTime DateTime = (DateTime)value;
            return DateTime.ToLocalTime().ToShortDateString();

        }


        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }


    }

Appliquer ce dans le XAML comme indiqué ci-dessous

Binding="{Binding Path=createdDateTime,Converter={StaticResource DateTimeConverter}}"

aussi changer la culture actuelle pour obtenir le format souhaité et les mêmes besoins à appliquer sur le démarrage de l'application

/// <summary>
        /// Set Culture
        /// </summary>
        private void SetCulture() {
            var newCulture = new CultureInfo("en-IN");
            newCulture.DateTimeFormat.ShortDatePattern = "dd-MMM-yyyy";
            newCulture.DateTimeFormat.LongDatePattern = "dd-MMM-yyyy";
            newCulture.DateTimeFormat.FullDateTimePattern = "dd-MMM-yyyy";
            CultureInfo.DefaultThreadCurrentCulture = newCulture;
            CultureInfo.DefaultThreadCurrentUICulture = newCulture;
            Thread.CurrentThread.CurrentCulture = newCulture;
            Thread.CurrentThread.CurrentUICulture = newCulture;
            FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(
                System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
        }

Que diriez-vous de changer la langue dans le derrière de code?

this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);

Le problème qui est d'éviter l'utilisation "this.Language = XmlLanguage.GetLanguage (Thread.CurrentThread.CurrentCulture.Name);" n'est pas vraiment une commune. Je ne sais pas tout utilisateur ici en France qui va changer le format de date à US ou au Japon un, juste parce que au moins aucun utilisateur ne sachant qu'un tel changement est possible (et ne sais pas comment le faire) ... Alors bien sûr, la « langue = » est pas parfait, mais dans beaucoup de nombreuses années de pratique WPF et Silverlight Je ne vois jamais un problème de ce genre avec tout utilisateur ... Donc, j'utilise toujours le « = Langage » truc, il est simple et couvrir 100% des besoins réels. Des cours d'autres solutions semblent être mieux, mais il n'y a pas besoin (et j'ai vu quelques implémentations qui sont loin d'être parfait pour comparer « language = » solution).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top