wpf의 StringFormat 지역화 문제


112

WPF 3.5SP1에서는 DataBindings의 마지막 기능인 StringFormat을 사용합니다.

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

내가 직면 한 문제는 날짜가 항상 영어로 형식화된다는 것입니다. 내 시스템은 프랑스어로되어 있지만? 날짜가 시스템 날짜를 따르도록하려면 어떻게해야합니까?


14
3 년 동안 높은 평가를 받았지만 답변이 표시되지 않았습니다! 사방에 슬픈 얼굴.
Gusdor

답변:


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

2
두통을 해결 해주셔서 감사합니다.
Skurmedel

9
큰. 그러나 응용 프로그램의 수명주기 동안 문화가 변경되는 경우 수행 할 작업 (예 : 사용자가 설정 대화 상자에서 선호하는 문화를 변경할 수 있음). 문서에 따르면 FrameworkElement.LanguageProperty.OverrideMetadata는 두 번 이상 호출 할 수 없습니다 (예외 발생)
TJKjaer

1
@pengibot이 솔루션은 저에게 효과적입니다. .net 4 / C # / WPF를 사용하고 있으며 OnStartup 메서드에 코드를 넣었습니다.
Björn

18
있습니다 실행 요소로부터 상속하지 않습니다 FrameworkElement A와 당신 바인드 날짜 등 만약 그렇다면, 실행은 다음에 대한 추가 호출이 필요합니다 대해서 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
우수한! 이것은 훌륭하게 작동했습니다! 필요한 곳에 이것을 추가하는 데 문제가 없습니다. BTW 귀하의 예제가 행방 불명입니다}
Johncl

3
잘했습니다. WPF는 현재 문화와 달리 기본적으로 미국 영어를 사용하는 것이 너무 이상합니다.
Kris Adams

12

나는 loraderon 의 대답이 대부분의 경우 훌륭하게 작동 한다고 덧붙이고 싶었습니다 . App.xaml.cs에 다음 코드 줄을 넣으면 TextBlock의 날짜가 올바른 문화권으로 형식이 지정됩니다.

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)

... 그러나 TextBlock에서 Run을 사용할 때 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에서 파생되지 않습니다. Loraderon의 답변을 수정하여 FrameworkElement뿐만 아니라 Run (FrameworkContentElement) 기반에 대해 그의 코드를 반복 할 수 있습니다.
Nathan Phillips

사람들을 위해 궁금 할 사람 :에 xmlns : GL = "CLR-네임 스페이스 :의 System.Globalization, 조립 = mscorlib에"
이고르 메스 자 로스

11

최상위 태그에 culture 바로 가기를 삽입하면됩니다.

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가 '올바른'문화라고 가정하는 것만 큼 나쁘다. 오히려 사용자 컴퓨터의 설정을 가져와야합니다.
misnomer

대단히 감사합니다. 이것이 제가 찾던 바로 그 것입니다! WPF가 en-EN이 모든 상황에 맞는 올바른 문화라고 생각하면 나만의 지역화를 사용할 수 있습니다. 개발 속도가 일상적인 개념 증명 응용 프로그램을 DatePicker작업하고 있기 때문에 단일 작업을 수행 하기 위해 수십 개의 코드 줄을 엉망으로 만들 시간이 없으므로이 쉬운 수정은 빨리 돌아와!
M463

내 경우에 대한 베스트 답변, 마침내 나이를 찾고 있습니다 :) 물론 맞습니다. 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);

그것은 즉시 재평가하지만 슬프게도 각각의 모든 루트 요소 (창)에 대해 개별적으로 설정되어야합니다
Firo

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.