web-dev-qa-db-ja.com

IetfLanguageTagのCultureInfoではなく、WPFバインディングで「実際の」CultureInfo.CurrentCultureを使用します

私の場合:

DateTime型のプロパティへのTextBlockバインディングがあります。ユーザーの地域設定にあるように表示したいです。

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

言語プロパティを WPF XAMLバインディングとCurrentCultureディスプレイ に設定しています:

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

ただし、このコード行では、Currents CultureのIetfLanguageTagが指定されたCultureInfoのデフォルト形式としてテキストを表示するだけであり、システム領域設定で選択された有効な値は次のようになります。

(たとえば、「de-DE」の場合dd.MM.yyyyが選択されたyyyy-MM-ddの代わりに使用されます

Region settings: not the default but yyy-MM-dd is used

すべてのバインディングでConverterCultureを定義せずに、バインディングが正しい形式を使用する方法はありますか?

コード内

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

適切なカルチャ設定を使用します。

編集:

希望どおりに機能しない別の方法(this.Language = ...など):

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

そして

<Binding Source="{x:Static glob:CultureInfo.CurrentCulture}" 
 Path="IetfLanguageTag" 
 ConverterCulture="{x:Static glob:CultureInfo.InvariantCulture}" />
36
Markus k

ConverterCultureを作成時に現在のカルチャに自動的に設定するバインディングのサブクラス(CultureAwareBindingなど)を作成できます。

これは完璧なソリューションではありませんが、おそらく唯一のソリューションです。文化を尊重するようにBindingを遡及的に強制すると、この動作に依存するWPFの他のコードが破損する可能性があるためです。

さらにサポートが必要な場合はお知らせください!

26
aKzenT

これはaKzenTからの回答の拡張です。彼らは、Bindingクラスのサブクラスを作成し、ConverterCultureをCurrentCultureに設定することを提案しました。答えは非常に単純ですが、一部の人々はそれを実装することにあまり抵抗がないかもしれないと感じているため、aKzenTの答えのコードバージョンをXAMLでの使用例と共有しています。

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

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

XAMLでこれを使用する方法の例

1)名前空間をXAMLファイルにインポートする必要があります。

<Page
    ...
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:myWpfLib="clr-namespace:MyWpfLibrary;Assembly=<Assembly_name>"
    ...
>

2)CultureAwareBindingの実際の使用法

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

UIが初期化される前に、次のコード行を配置します。これは私のために働いた。

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

(そして、明示的なカルチャパラメータをすべて削除します)

5
Alan Hauge

あなたの2回目の試みは近かったので、私のために働く解決策に私を導いた。

ConverterCultureの設定に関する問題は、Converterがある場合にのみ使用されることです。そのため、フォーマットをパラメーターとして取る単純なStringFormatConverterを作成するだけです。

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();
    }
}

次に、バインディングを調整できます(コンバーターの名前空間を「my」としてインポートしたと仮定)

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

そのコードを使用して、自分のニーズに合った適切な結果を出します。それがあなたを満たしてくれることを願っています:-)! 「TryParse」ができない場合は、おそらく例外をスローする方が良いでしょう。あなた次第。

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;
    }
}

使用法:

<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>
2
Eric Ouellet

すべてのバインディングの更新を回避するハック/回避策を思いつきました。このコードをメインウィンドウのコンストラクターに追加します。

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

リフレクションを使用しているため、将来的に機能するという保証はありませんが、現時点では機能します(.NET 4.6)。

2

IValueConverterを使用してDateTime Converterを作成できます

[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();
        }


    }

以下に示すように、XAMLでこれを適用します

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

また、現在のカルチャを変更して目的の形式を取得し、アプリケーションの起動時に同じニーズを適用する必要があります

/// <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)));
        }
0
ASHOK MANGHAT