WPFでのStringFormatローカリゼーションの問題


112

WPF 3.5SP1では、DataBindingsで最後の機能StringFormatを使用します。

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

私が直面している問題は、日付が常に英語でフォーマットされていることです...私のシステムはフランス語ですが?日付をシステム日付に強制するにはどうすればよいですか?


14
3年間、非常に評価の高い質問ですが、回答はありません 悲しい顔が丸くなっています。
Gusdor 2012

回答:


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

WPFでの国際化ウィザードの作成から


17
ええ、これはかなり迷惑です。+1
Szymon Rozga 2009

2
私の頭痛を解決してくれてありがとう。
Skurmedel

9
すごい。しかし、アプリケーションのライフサイクル中にカルチャが変更された場合はどうするか(たとえば、ユーザーは設定ダイアログで好みのカルチャを変更できます)。ドキュメントによると、FrameworkElement.LanguageProperty.OverrideMetadataを複数回呼び出すことはできません(例外がスローされます)
TJKjaer

1
@pengibotこのソリューションは私に適しています。.net 4 / C#/ WPFを使用していて、コードをOnStartupメソッドに配置しました。
ビョルン2013年

18
注意ラン要素を継承しないのFrameworkElementにあなたバインド日付などそうならば、ファイル名を指定して実行は、あなたがのために余分な呼び出しが必要になりますtypeof演算(System.Windows.Documents.Run)
マットファーガソン

90

次のxml名前空間を定義します。

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

次に、この素​​晴らしい修正を見てください。

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

私はこれがグローバルな修正ではないことをよく知っています、そしてあなたはあなたのバインディングのそれぞれでそれを必要とするでしょう、しかし確かにそれはちょうど良いXAMLですか?私の知る限りでは、バインディングが次に更新されるときには、正しいものCultureInfo.CurrentCultureまたはユーザーが指定したものを使用します。

このソリューションは、バインディングを正しい値で即座に更新しますが、非常にまれで無害な何かのための多くのコードのようです。


4
優れた!これは素晴らしく機能しました!これを必要ないくつかの場所に追加しても問題ありません。ところで、あなたの例には}がありません
Johncl

3
素晴らしい仕事。現在のカルチャとは対照的に、WPFがデフォルトでUS-Englishを使用するのは奇妙です。
クリスアダムス

12

ロラデロンの答えがほとんどの場合にうまく機能することを追加したかっただけです。App.xaml.csに次のコード行を配置すると、TextBlocksの日付が正しいカルチャでフォーマットされます。

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

私は「ほとんどの場合」と言います。たとえば、これはそのまま使用できます。

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

...しかし、RunをTextBlockで使用すると、DateTimeはデフォルトのカルチャでフォーマットされます。

<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")

これを機能させるには、Gusdorの答え、つまり、ConverterCulture = {x:Static gl:CultureInfo.CurrentCulture}をバインディングに追加する必要がありました

<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)

この追加の答えが誰かに役立つことを願っています。


実際、RunはFrameworkElementから派生していません。ロラデロンの回答を変更して、Run(FrameworkContentElement)のベースとFrameworkElementのコードを繰り返すようにすることができます。
Nathan Phillips

疑問に思う人のために:xmlns:gl = "clr-namespace:System.Globalization; assembly = mscorlib"
Igor Meszaros

11

トップレベルのタグにカルチャーショートカットを挿入するだけです。

xml:lang="de-DE"

例えば:

<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
しかし、これはen-USが「正しい」文化であると仮定するのと同じくらい悪いです。むしろ、ユーザーのマシンから設定を取得する必要があります。
ミスノマー2013年

本当にありがとうございました。これがまさに私が探していたものです!en-ENがどのような状況にとっても適切な文化であるとWPFが判断した場合は、自分のローカリゼーションを使用することもできます。私は、開発速度が1日のオーダーである概念実証アプリケーションに取り組んでいるため、1つDatePickerのジョブを実行するためだけに数十のコード行をいじる時間はないので、この簡単な修正で私はすぐに軌道に戻りました!
M463 2015

私のケースのベストアンサー、最終的に年齢を探していました:)そしてもちろんそれは正しいです、あなたはそのen-USまたはそれがde-DEであると仮定します...人々は常に単純な解決策で問題を抱えています-.-
MushyPeas

10

既に述べたように、XAMLはデフォルトでインバリアントカルチャ(en-US)に設定されており、

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

カルチャを現在のカルチャの言語のデフォルトカルチャに設定します。しかし、コメントは間違っています。これはしませ現在のカルチャを使用ユーザーが行ったカスタマイズは表示されないため、常に言語のデフォルトになります。

実際にカスタマイズして、現在のカルチャを使用するには、設定する必要がありますConverterCultureと一緒にStringFormatのように、

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

glあなたのルート要素にグローバル名前空間として定義されます

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

あなたの代わりにXAMLのコードを介してこれをやっている場合は、次のようにそれはです:binding.ConverterCulture = System.Globalization.CultureInfo.CurrentCulture;
Metalogic

8

プログラムの実行中に言語を変更する必要がある場合は、ルート要素のLanguageプロパティを変更するだけでかまいません(これがすぐに影響するのか、サブ要素を再作成する必要があるのか​​、私の場合は少なくとも機能します)。

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

それはすぐに再評価したが、悲しいことに別々一人ひとりrootelement(ウィンドウ)のために設定する必要があります
フィーロ

6

次のような要素でもローカリゼーションを切り替える完全なコード<Run />は次のとおりです。

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

実行時にカルチャー情報を変更したい場合は、ビヘイビアーを使用できます(以下を参照)

  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

XAMLではなくコードで作業している場合は、ConverterCultureを次のように設定できます。

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

デフォルトのカルチャ定義の使用とユーザーのカスタマイズされたカルチャ定義の使用の微妙な違いを指摘してくれた@KZeiseへの称賛。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.