[英]Use “real” CultureInfo.CurrentCulture in WPF Binding, not CultureInfo from IetfLanguageTag
就我而言:
我有一個文本塊綁定到日期時間類型的屬性。 我希望它按照用戶的區域設置顯示。
<TextBlock Text="{Binding Date, StringFormat={}{0:d}}" />
我將 Language 屬性設置為WPF XAML Bindings 和 CurrentCulture Display說:
this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag);
但是使用這行代碼,它只是將文本顯示為 CultureInfo 的默認格式,CurrentCulture 的 IetfLanguageTag 說,而不是系統區域設置中選擇的有效值說:
(例如,對於“de-DE”,使用dd.MM.yyyy代替選定的yyyy-MM-dd )
有沒有辦法 Binding 使用正確的格式而不在每個 Binding 上定義 ConverterCulture?
在代碼中
string.Format("{0:d}",Date);
使用正確的文化設置。
編輯:
另一種不能按預期工作的方式(就像 this.Language =... 那樣):
xmlns:glob="clr-namespace:System.Globalization;assembly=mscorlib"
和
<Binding Source="{x:Static glob:CultureInfo.CurrentCulture}"
Path="IetfLanguageTag"
ConverterCulture="{x:Static glob:CultureInfo.InvariantCulture}" />
您可以創建綁定的子類(例如 CultureAwareBinding),它在創建時將 ConverterCulture 自動設置為當前區域性。
這不是一個完美的解決方案,但它可能是唯一的解決方案,因為追溯強制綁定尊重文化可能會破壞 WPF 中取決於此行為的其他代碼。
如果您需要更多幫助,請告訴我!
這是 aKzenT 答案的擴展。 他們建議我們應該創建一個 Binding class 的子類,並將 ConverterCulture 設置為 CurrentCulture。 盡管答案非常直接,但我覺得有些人可能不太願意實施它,所以我將 aKzenT 答案的代碼版本與如何在 XAML 中使用它的示例分享。
using System;
using System.Globalization;
using System.Windows.Data;
namespace MyWpfLibrary
{
public class CultureAwareBinding : Binding
{
public CultureAwareBinding()
{
ConverterCulture = CultureInfo.CurrentCulture;
}
}
}
如何在 XAML 中使用它的示例
1)您需要將命名空間導入 XAML 文件:
<Page
...
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:myWpfLib="clr-namespace:MyWpfLibrary;assembly=<assembly_name>"
...
>
2) CultureAwareBinding 在現實世界中的使用
<Textblock Text="{myWpfLib:CultureAwareBinding Path=Salary, Source=Contact, StringFormat={}{0:C}}" />
在初始化任何 UI 之前放置以下代碼行。 這對我有用。
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
(並刪除所有顯式文化參數)
我使用該代碼並根據我的需要獲得適當的結果。 希望它可以滿足您的需求:-)。 如果不能“TryParse”,也許你最好拋出異常。 由你決定。
public sealed class CurrentCultureDoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((double)value).ToString((string)parameter ?? "0.######", CultureInfo.CurrentCulture);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
double result;
if (Double.TryParse(value as string, NumberStyles.Number, CultureInfo.CurrentCulture, out result))
{
return result;
}
throw new FormatException("Unable to convert value:" + value);
// return value;
}
}
用法:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:simulatorUi="clr-namespace:SimulatorUi"
xmlns:Converter="clr-namespace:HQ.Wpf.Util.Converter;assembly=WpfUtil" x:Class="SimulatorUi.DlgTest"
Title="DlgTest" Height="300" Width="300">
<Window.DataContext>
<simulatorUi:DlgTestModel/>
</Window.DataContext>
<Window.Resources>
<Converter:CurrentCultureDoubleConverter x:Key="CurrentCultureDoubleConverter"/>
</Window.Resources>
<Grid>
<TextBox Text="{Binding DoubleVal, Converter={StaticResource CurrentCultureDoubleConverter}}"/>
</Grid>
</Window>
我想出了一個避免更新所有綁定的技巧/解決方法。 將此代碼添加到主 window 的構造函數中。
XmlLanguage language = XmlLanguage.GetLanguage("My-Language");
typeof(XmlLanguage).GetField("_compatibleCulture", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(language, CultureInfo.CurrentCulture);
this.Language = language;
由於它使用反射,因此不能保證它將來會起作用,但現在它可以(.NET 4.6)。
您的第二次嘗試很接近,並讓我找到了一個對我有用的解決方案。
設置 ConverterCulture 的問題在於它僅在您擁有 Converter 時使用。 因此,只需創建一個簡單的 StringFormatConverter ,將格式作為其參數:
public sealed class StringFormatConverter : IValueConverter
{
private static readonly StringFormatConverter instance = new StringFormatConverter();
public static StringFormatConverter Instance
{
get
{
return instance;
}
}
private StringFormatConverter()
{
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.Format(culture, (string)parameter, value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
然后您可以調整綁定(假設您已將轉換器的命名空間導入為“my”)
<TextBlock Text="{Binding Date, Converter={x:Static my:StringFormatConverter.Instance}, ConverterCulture={x:Static glob:CultureInfo.CurrentCulture}, ConverterParameter={}{0:d}}" />
我們可以使用 IValueConverter 創建一個 DateTime 轉換器
[ValueConversion(typeof(DateTime), typeof(String))]
class DateTimeToLocalConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is DateTime)) return "Invalid DateTime";
DateTime DateTime = (DateTime)value;
return DateTime.ToLocalTime().ToShortDateString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
在 XAML 中應用它,如下所示
Binding="{Binding Path=createdDateTime,Converter={StaticResource DateTimeConverter}}"
還要更改當前的文化以獲得所需的格式,並且需要在應用程序啟動時應用相同的格式
/// <summary>
/// Set Culture
/// </summary>
private void SetCulture() {
var newCulture = new CultureInfo("en-IN");
newCulture.DateTimeFormat.ShortDatePattern = "dd-MMM-yyyy";
newCulture.DateTimeFormat.LongDatePattern = "dd-MMM-yyyy";
newCulture.DateTimeFormat.FullDateTimePattern = "dd-MMM-yyyy";
CultureInfo.DefaultThreadCurrentCulture = newCulture;
CultureInfo.DefaultThreadCurrentUICulture = newCulture;
Thread.CurrentThread.CurrentCulture = newCulture;
Thread.CurrentThread.CurrentUICulture = newCulture;
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(
System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
}
改變后面代碼中的語言怎么樣?
this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);
避免使用“this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);”的問題不是一個真正的常見的。 我不知道法國有任何用戶會將日期格式更改為美國或日本格式,因為至少沒有用戶知道這樣的更改是可能的(並且不知道該怎么做)......所以當然“語言=”並不完美,但是在WPF和Silverlight的多年實踐中,我從未見過任何用戶出現這種問題......所以我仍然使用“語言=”技巧,它簡單而覆蓋100%的真實需求。 當然其他解決方案似乎更好,但沒有必要(我看到一些與“語言=”解決方案相比遠非完美的實現)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.