WPF에서 문화를 설정하고 변경하는 방법
저는 있습니다.사용자가 언어(문화)를 변경할 수 있는 NET 4.0 WPF 응용 프로그램 사용자가 언어를 선택하고 해당 CultureInfo를 만들고 다음을 설정할 수 있습니다.
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
C# 코드에서는 이것이 잘 작동합니다.그러나 WPF 제어에서 문화는 여전히 미국 내에 있습니다.이것은 예를 들어 날짜가 현재 문화에 맞는 것 대신 미국 형식으로 표시된다는 것을 의미합니다.
보아하니, 이것은 버그가 아닙니다.MSDN과 StackOverflow에 대한 여러 블로그 게시물 및 기사에 따르면 WPF 언어는 자동으로 현재 문화를 따르지 않습니다.이 작업을 수행할 때까지 다음 작업이 수행됩니다.
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(
XmlLanguage.GetLanguage(CultureInfo.CurrentUICulture.IetfLanguageTag)));
wpf의 StringFormat 현지화 문제 예제를 참조하십시오.
저는 여기서 무슨 일이 일어나고 있는지 완전히 이해하지 못합니다.모든 프레임워크 요소의 언어 속성이 현재 문화로 설정된 것 같습니다.어쨌든, 효과가 있습니다.응용 프로그램이 시작되고 이제 모든 컨트롤이 예상대로 작동하고 날짜 등이 현재 문화에 따라 포맷될 때 이 작업을 수행합니다.
MSDN MSDN에 따르면FrameworkElement.LanguageProperty.OverrideMetadata한 번만 호출할 수 있습니다.그리고 실제로 제가 (사용자가 언어를 변경할 때) 다시 호출하면 예외가 발생합니다.그래서 저는 제 문제를 제대로 해결하지 못했습니다.
질문:애플리케이션 라이프사이클에서 WPF의 문화를 한 번 이상 그리고 언제라도 안정적으로 업데이트하려면 어떻게 해야 합니까?
(저는 이것을 조사할 때 발견했습니다: http://www.nbdtech.com/Blog/archive/2009/03/18/getting-a-wpf-application-to-pick-up-the-correct-regional.aspx 그리고 그는 그곳에서 일하는 무언가를 가지고 있는 것 같습니다.하지만, 저는 제 애플리케이션에서 이것을 어떻게 하는지 상상할 수 없습니다.열려 있는 모든 창과 컨트롤의 언어를 업데이트하고 기존 바인딩을 모두 새로 고쳐야 할 것 같습니다.)
나는 여기서 차임벨을 울릴 것입니다.
사용하여 성공적으로 이 작업을 수행했습니다.OverrideMetadata()OP가 언급한 방법:
var lang = System.Windows.Markup.XmlLanguage.GetLanguage(MyCultureInfo.IetfLanguageTag);
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(lang)
);
그러나 WPF에서 시스템 문화가 날짜와 숫자 값에 적용되는 사례를 발견했습니다.알고 보니 이것들은 다음과 같은 가치들이었습니다.<Run>요소들.그것은 발생했습니다.System.Windows.Documents.Run는 클스가않음에서 .System.Windows.FrameworkElement 그서메타우선는위순의터래이에 있는 .FrameworkElement분명히 효과가 없었습니다.
System.Windows.Documents.Run그것을 계승합니다.Language의 System.Windows.FrameworkContentElement대신.
따라서 분명한 해결책은 데이터를 오버라이드하는 것이었습니다.FrameworkContentElement같은 방법으로작업을 수행하는 동안 예외가 발생했습니다(PropertyMetadata가 시스템 유형에 이미 등록되어 있습니다).윈도우.FrameworkContentElement)의 다음 후손에 대해 수행해야 했습니다.Run 신대,System.Windows.Documents.TextElement:
FrameworkContentElement.LanguageProperty.OverrideMetadata(
typeof(System.Windows.Documents.TextElement),
new FrameworkPropertyMetadata(lang)
);
그리고 그것이 제 모든 문제를 해결했습니다.
의하클가몇개다있니습더래의 하위 가 몇 개 더 .FrameworkContentElement완전성을 위해 메타데이터도 재정의해야 합니다.
저는 제가 질문에서 요청한 것을 정확히 할 방법을 찾지 못했습니다.이 경우 모든 사용자 컨트롤이 다음을 포함하는 Superclass에서 상속되도록 함으로써 문제를 해결했습니다.
/// <summary>
/// Contains shared logic for all XAML-based Views in the application.
/// Views that extend this type will have localization built-in.
/// </summary>
public abstract class ViewUserControl : UserControl
{
/// <summary>
/// Initializes a new instance of the ViewUserControl class.
/// </summary>
protected ViewUserControl()
{
// This is very important! We make sure that all views that inherit
// from this type will have localization built-in.
// Notice that the following line must run before InitializeComponent() on
// the view. Since the supertype's constructor is executed before the type's
// own constructor (which call InitializeComponent()) this is as it
// should be for classes extending this
this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag);
}
}
사용자가 언어를 변경하면 현재 실행 중인 모든 사용자 컨트롤의 새 인스턴스를 만듭니다.
이것으로 저의 문제가 해결되었습니다.그러나 이러한 작업을 "자동"(예: 인스턴스화된 개체를 추적하지 않고) 수행할 수 있는 방법이 필요합니다.
"Metadata 재정의를 여러 번 호출할 수 없음" 예외를 피하는 방법을 잘 모르겠습니다.
해결 방법으로 사용자가 앱에서 UI 문화를 변경할 때 해당 문화로 앱을 다시 시작하여 새로운 문화를 명령줄 인수로 전달할 수 있습니다.사용자가 문화를 자주 바꾸지 않는 한, 이것은 합리적인 해결책으로 들립니다.
단 2센트: 독일어 어셈블리로 ComponentOne WPF 컨트롤(DataGrid 및 C1DatePicker)을 구현하려고 할 때 거의 미쳐버린 후 이 페이지를 발견했습니다.
올바른 방향으로 진행되는 것 같습니다. 방금 위의 코드를 App.xaml.cs / Application_startup 루틴에 입력했고 이제 C1DatePicker의 독일어 날짜/시간 형식이 마침내 작동합니다.
그 후에 바로 데이터 그리드를 테스트해야 합니다.
private void Application_Startup(object sender, StartupEventArgs e)
{
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(
System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentUICulture.IetfLanguageTag)));
}
감사합니다!
업데이트: WPF에 대해 테스트된 C1 데이터 그리드 - 작동합니다!이렇게 하면 응용프로그램의 국제 날짜/시간 설정과 관련하여 발생한 모든 문제가 해결됩니다.좋았어!
적응형 재정의 메타데이터
할 경우 Language속성은 텍스트를 업데이트하지 않습니다.
그러나 메타데이터를 한 번 설정하고 새 컨트롤이 자동으로 현재 문화를 사용하도록 하는 메타데이터를 재정의하는 방법이 있습니다.
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(
System.Windows.Markup.XmlLanguage.Empty,
default(PropertyChangedCallback),
_CoerceCurrentXmlLang));
어디서CoerceValueCallback이라
private static object _CoerceCurrentXmlLang(DependencyObject d, object baseValue)
{
var lang = baseValue as System.Windows.Markup.XmlLanguage;
var culture = System.Globalization.CultureInfo.CurrentUICulture;
return lang != null && lang.IetfLanguageTag.Equals(culture.Name, StringComparison.InvariantCultureIgnoreCase)
? lang
: System.Windows.Markup.XmlLanguage.GetLanguage(culture.Name);
}
새로 생성된 컨트롤은 기본값을 얻기 때문에 그 자체로는 충분하지 않습니다.System.Windows.Markup.XmlLanguage.Empty강요당하지 않고 말입니다.그러나 설정할 경우xml:lang=""그러면 각 새 컨트롤이 상위 컨트롤로부터 값을 상속받고 해당 값을 강제로 상속하는 것을 확인할 수 있습니다.그 결과 창에 추가된 새 컨트롤이 현재 언어를 사용합니다.
PS WPF의 많은 것들과 마찬가지로, 그들이 물건들을 보관하는 데 그렇게 열심이지 않았다면 꽤 단순했을 것입니다.internal.DefaultValueFactory훨씬 더 우아한 방법이 될 겁니다
다시 로드 중
가장 극단적이지만 신뢰할 수 있는 재로드 방법은 새 주 창을 만들고 이전 주 창을 삭제하는 것입니다.
거의 극단적이지만 정확하지 않은 것은 기본 창의 매우 간단한 창에서만 언어 설정이 변경되도록 조정하는 것이며, 로드된 내용이 거의 없고 모든 항목에 대해 속성 변경 알림을 강제로 적용할 수 있는 보기 모델에 완전히 데이터 바인딩되는 것은 거의 없습니다.
이 질문에 대한 기존 답변에는 다른 제안이 있습니다.
저도 거의 같은 문제를 가지고 있었습니다.
저는 이것을 찾았습니다: http://www.codeproject.com/Articles/35159/WPF-Localization-Using-RESX-Files (원래 출처는 아닐 수 있습니다).
"UICulture"라는 이름의 마크업 확장에 대해 설명합니다.지역화가 필요한 모든 프레임워크 요소(XAML)의 Language 속성에 첨부된 "확장"입니다.
UI 언어 변경 이벤트를 발생시키면 백그라운드의 정적 확장 관리자가 등록된 모든 프레임워크 요소를 업데이트합니다.
완전히 당신의 답은 아니지만, 저는 이것을 자원을 다시 로드하는 데 사용했습니다.하지만 창문을 다시 열어야 합니다...
List<Uri> dictionaryList = new List<Uri>();
foreach (ResourceDictionary dictionary in Application.Current.Resources.MergedDictionaries)
{
dictionaryList.Add(dictionary.Source);
}
Application.Current.Resources.MergedDictionaries.Clear();
foreach (Uri uri in dictionaryList)
{
ResourceDictionary resourceDictionary1 = new ResourceDictionary();
resourceDictionary1.Source = uri;
Application.Current.Resources.MergedDictionaries.Add(resourceDictionary1);
}
병합된 리소스 사전/동적 리소스 앱을 사용하여 문자열을 변경합니다.그러나 올바른 자동 날짜/시간/기타 지역 형식을 위해 언어를 설정합니다.Application.Current.MainWindow.Language자식에게 상속되고 자동으로 업데이트됩니다.적어도 Net 5.0에서는...
var l = System.Globalization.CultureInfo.CreateSpecificCulture(localeName);
Thread.CurrentThread.CurrentUICulture = l;
Thread.CurrentThread.CurrentCulture = l;
System.Globalization.CultureInfo.DefaultThreadCurrentCulture = l;
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = l;
// Order is important!!! Set Threads before MainWindow.Language,
// otherwise regional settings are inconsistent
Application.Current.MainWindow.Language = XmlLanguage.GetLanguage(l.Name);
언급URL : https://stackoverflow.com/questions/4041197/how-to-set-and-change-the-culture-in-wpf
'programing' 카테고리의 다른 글
| 프로젝트에서 코코아 포드를 제거하는 방법은 무엇입니까? (0) | 2023.04.29 |
|---|---|
| ASP에서 가장 좋은 방법은 무엇입니까?현재 도메인을 얻기 위한 NET? (0) | 2023.04.29 |
| arc4random_uniform()의 범위 사이에 난수를 어떻게 만들 수 있습니까? (0) | 2023.04.29 |
| Xcode 10 오류: 여러 명령이 생성됩니다. (0) | 2023.04.29 |
| C# - Excel 워크시트를 프로그래밍 방식으로 추가하는 방법 - Office XP / 2003 (0) | 2023.04.19 |