it-swarm.com.de

StringFormat Lokalisierungsprobleme in wpf

In WPF 3.5SP1 verwende ich das letzte Feature StringFormat in DataBindings:

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

Das Problem, mit dem ich konfrontiert bin, ist, dass das Datum immer auf Englisch formatiert ist ... obwohl mein System auf Französisch ist? Wie kann ich das Datum zwingen, dem Systemdatum zu folgen?

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

Von Erstellen eines internationalisierten Wizard in WPF

192
loraderon

Definieren Sie den folgenden XML-Namespace:

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

Nun sieh dir diesen fantastischen Fix an:

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

Ich bin mir bewusst, dass dies kein globaler Fix ist und Sie werden es für jede Ihrer Bindungen benötigen, aber das ist doch nur eine gute XAML? Soweit mir bekannt ist, wird das nächste Mal, wenn die Bindung aktualisiert wird, der korrekte CultureInfo.CurrentCulture oder was auch immer Sie angegeben haben, verwendet.

Diese Lösung aktualisiert Ihre Bindings sofort mit den korrekten Werten aber es scheint viel Code für etwas zu sein, das so selten und harmlos ist.

80
Gusdor

Fügen Sie einfach die Kulturverknüpfung in das Tag der obersten Ebene ein:

xml:lang="de-DE"

z.B.:

<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

Ich wollte nur hinzufügen, dass die Antwort von loraderon in den meisten Fällen gut funktioniert. Wenn ich die folgende Codezeile in App.xaml.cs stecke, werden die Datumsangaben in meinen TextBlocks in der richtigen Kultur formatiert.

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

Ich sage 'die meisten Fälle'. Zum Beispiel wird dies von Anfang an funktionieren:

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

... aber wenn Sie Runs in einem TextBlock verwenden, wird DateTime in der Standardkultur formatiert.

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

Damit dies funktioniert, brauchte ich die Antwort von Gusdor , nämlich das Hinzufügen von ConverterCulture = {x: Static gl: CultureInfo.CurrentCulture} zur Bindung.

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

Ich hoffe, diese zusätzliche Antwort wird für jemanden von Nutzen sein.

8

Wenn Sie die Sprache ändern müssen, während das Programm ausgeführt wird, können Sie einfach die Language-Eigenschaft in Ihrem Stammelement ändern.

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

Wie bereits erwähnt, verwendet XAML standardmäßig die invariante Kultur (en-US), die Sie verwenden können

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

um die Kultur auf die Standardkultur für die Sprache der aktuellen Kultur festzulegen. Aber der Kommentar ist falsch. Dies verwendet nicht die aktuelle Kultur. Da der Benutzer möglicherweise keine Anpassungen sieht, ist dies immer die Standardeinstellung für die Sprache. 

Um die aktuelle Kultur tatsächlich mit Anpassungen zu verwenden, müssen Sie die Variable ConverterCulture zusammen mit der Variable StringFormat wie in festlegen 

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

mit der Variable gld als globaler Namespace in Ihrem Stammelement

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

Der vollständige Code zum Wechseln der Lokalisierung in Elementen wie <Run /> lautet wie folgt:

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

Wenn Sie Kulturinformationen zur Laufzeit ändern möchten, können Sie ein Verhalten verwenden (siehe unten).

  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

Wenn Sie nicht mit XAML, sondern mit Code arbeiten, können Sie ConverterCulture wie folgt einstellen:

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

Ein großes Lob an @KZeise für den Hinweis auf den subtilen Unterschied zwischen der Verwendung der Standardkulturdefinition und der benutzerdefinierten Kulturdefinition des Benutzers.

0
Metalogic