web-dev-qa-db-ja.com

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

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

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

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

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

から 国際化されたWizard)の作成

202
loraderon

次の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または指定したものが使用されます。

このソリューションはすぐに正しい値でBindingsを更新します しかし、非常にまれで無害な何かのための多くのコードのようです。

82
Gusdor

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

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>
10
Gerrit Horeis

loraderonの答えがほとんどの場合うまくいくことを付け加えたかっただけです。 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}をBindingに追加する必要がありました。

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

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

10

既に述べたように、XAMLのデフォルトは不変カルチャ(en-US)であり、使用できます

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

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

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

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

ルート要素のグローバル名前空間としてgldefinedを使用

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

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

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

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

実行時にカルチャ情報を変更する場合は、動作を使用できます(以下を参照)

  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

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

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

デフォルトのカルチャ定義を使用することと、ユーザーがカスタマイズしたカルチャ定義を使用することの微妙な違いを指摘してくれた@KZeiseに感謝します。

0
Metalogic