Wpf'de StringFormat Yerelleştirme sorunları


112

WPF 3.5SP1'de DataBindings'deki son StringFormat özelliğini kullanıyorum:

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

Karşılaştığım sorun, tarihin her zaman İngilizce olarak biçimlendirilmesi ... sistemim Fransızca olmasına rağmen? Tarihi sistem tarihini takip etmeye nasıl zorlayabilirim?


14
3 yıl yüksek puan alan bir soru ama hiçbir yanıt işaretlenmemiş! Her yerde üzgün yüzler.
Gusdor

Yanıtlar:


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

Gönderen WPF bir Internationalized Sihirbazı oluşturma


17
Evet, bu oldukça can sıkıcı. +1
Szymon Rozga

2
Baş ağrımı çözdüğün için teşekkürler.
Skurmedel

9
Harika. Ancak uygulamanın yaşam döngüsü boyunca kültür değişirse ne yapılmalı (örneğin, kullanıcı bir ayarlar iletişim kutusunda tercih ettiği kültürü değiştirebilir). FrameworkElement.LanguageProperty.OverrideMetadata belgelerine göre birden fazla
çağrılamaz

1
@pengibot Bu çözüm benim için çalışıyor. .Net 4 / C # / WPF kullanıyorum ve kodu OnStartup yöntemine koyuyorum.
Björn

18
Çalıştır öğesinin FrameworkElement'ten miras almadığına dikkat edin , bu nedenle tarihleri ​​vb. Bir Çalıştırmaya bağlarsanız , typeof (System.Windows.Documents.Run)
Mat Fergusson

90

Aşağıdaki xml ad alanını tanımlayın:

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

Şimdi şu harika düzeltmeye bakın:

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

Bunun genel bir düzeltme olmadığının ve Bağlamalarınızın her birinde buna ihtiyaç duyacağınızın farkındayım, ancak bu kesinlikle iyi bir XAML mi? Bildiğim kadarıyla, bir dahaki sefere ciltleme güncellemeleri doğru CultureInfo.CurrentCultureveya sağladığınız şeyi kullanacaktır .

Bu çözüm, Bağlamalarınızı doğru değerlerle hemen güncelleyecektir. ancak çok nadir ve zararsız bir şey için çok fazla kod gibi görünüyor.


4
Mükemmel! Bu harika çalıştı! Bunu ihtiyaç duyulan birkaç yere eklemekte sorun yaşamıyorum. Btw örneğinizde a} eksik
Johncl

3
Harika iş. WPF'nin mevcut kültürün aksine varsayılan olarak ABD İngilizcesini kullanması çok garip.
Kris Adams

12

Sadece loraderon'un cevabının çoğu durumda harika olduğunu eklemek istedim . Aşağıdaki kod satırını App.xaml.cs dosyama koyduğumda, TextBlock'larımdaki tarihler doğru kültürde biçimlendiriliyor.

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

'Çoğu vaka' diyorum, örneğin, bu kutudan çıkar çıkmaz:

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

... ancak bir TextBlock'ta Çalıştır'ı kullanırken, DateTime varsayılan kültürde biçimlendirilir.

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

Bunun işe yaraması için Gusdor'un cevabına, yani ConverterCulture = {x: Static gl: CultureInfo.CurrentCulture} ' ı Binding'e ekledim .

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

Umarım bu ek cevap birileri için yararlı olur.


Aslında, Çalıştırma FrameworkElement'ten türetilmez. Loraderon'un cevabını değiştirerek kodunu Run (FrameworkContentElement) ve FrameworkElement için tekrarlamayı deneyebilirsiniz.
Nathan Phillips

Merak edenler için: xmlns: gl = "clr-namespace: System.Globalization; assembly = mscorlib"
Igor Meszaros

11

Kültür kısayolunu üst düzey etikete eklemeniz yeterlidir:

xml:lang="de-DE"

Örneğin:

<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
Ancak bu, en-US'nin 'Doğru' kültür olduğunu varsaymak kadar kötü. Ayarları kullanıcının makinesinden alması gerekir.
yanlış isim

Çok teşekkür ederim, tam da aradığım buydu! WPF, en-EN'nin herhangi bir durum için doğru kültür olduğunu düşünüyorsa, ben de kendi yerelleştirmemle yapabilirim. Geliştirme hızının günün sırası olduğu bir kavram kanıtı uygulaması üzerinde çalıştığım için, sırf DatePickerişini yapacak tek bir tane elde etmek için düzinelerce kod satırıyla uğraşmaya zaman yok, bu yüzden bu kolay düzeltme çabucak yoluma geri dönüyorum!
M463

benim durumum için en iyi cevap, sonunda yaşları arıyordum :) ve tabii ki doğru, ya en-US olduğunu varsayarsınız ya da DE-DE olduğunu varsayarsınız ... insanlar her zaman basit çözümlerle problem
yaşarlar

10

Daha önce belirtildiği gibi, XAML varsayılan olarak değişmez kültürü (en-US) kullanır ve

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

kültürü, mevcut kültürün dili için varsayılan kültüre ayarlamak. Ancak yorum yanlıştır; Bu mu değil kullanıcı yapmış olabileceğiniz özelleştirmeleri görmez olarak her zaman dilin varsayılan olacaktır, mevcut kültür kullanın.

Mevcut kültürü özelleştirmelerle gerçekten kullanmak ConverterCultureiçin StringFormat, aşağıdaki gibi birlikte ayarlamanız gerekir :

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

ile glkök elemanı global ad olarak tanımlanır

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

Bunu XAML yerine kod aracılığıyla yapıyorsanız, aşağıdaki gibidir:binding.ConverterCulture = System.Globalization.CultureInfo.CurrentCulture;
Metalogic

8

Program çalışırken dili değiştirmeniz gerekirse, kök öğenizdeki Dil özelliğini değiştirebilirsiniz (bunun anında bir etkisi olup olmadığından veya alt öğenin yeniden oluşturulması gerekip gerekmediğinden emin değilim, benim durumumda en azından işe yarıyor)

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

anında yeniden değerlendiriyor ancak ne yazık ki her bir rootelement (pencere) için ayrı ayrı
ayarlanması gerekiyor

6

Yerelleştirmeyi aşağıdaki gibi öğelerde değiştirmek için tam kod <Run />şudur:

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

Çalışma zamanında kültür bilgisini değiştirmek istiyorsanız, bir davranış kullanabilirsiniz (aşağıya bakın)

  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 yerine kod üzerinde çalışıyorsanız, ConverterCulture'ı aşağıdaki gibi ayarlayabilirsiniz:

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

Varsayılan kültür tanımını kullanmakla kullanıcının özelleştirilmiş kültür tanımını kullanmak arasındaki ince farka işaret ettiği için @KZeise'e tebrikler.


-3

Texblock yerine Etiket (Cultture dahil) kullanın

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.