45

就我而言:

我有一个文本块绑定到日期时间类型的属性。我希望它按照用户的区域设置显示。

<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

区域设置:不是默认但使用yyy-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}" />
4

9 回答 9

30

您可以创建绑定的子类(例如 CultureAwareBinding),它在创建时将 ConverterCulture 自动设置为当前区域性。

这不是一个完美的解决方案,但它可能是唯一的解决方案,因为追溯强制绑定尊重文化可能会破坏 WPF 中取决于此行为的其他代码。

如果您需要更多帮助,请告诉我!

于 2011-05-09T13:23:05.637 回答
22

这是 aKzenT 答案的扩展。他们建议我们应该创建一个 Binding 类的子类,并将 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}}" />
于 2013-11-05T18:38:29.573 回答
9

在初始化任何 UI 之前放置以下代码行。这对我有用。

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

(并删除所有显式文化参数)

于 2016-07-25T12:37:30.403 回答
4

您的第二次尝试很接近,并让我找到了一个对我有用的解决方案。

设置 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}}" />
于 2011-08-25T21:08:43.020 回答
3

我使用该代码并根据我的需要获得适当的结果。希望它能满足你的:-)!如果不能“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>
于 2015-04-21T20:48:07.853 回答
2

我想出了一个避免更新所有绑定的技巧/解决方法。将此代码添加到主窗口的构造函数中。

XmlLanguage language = XmlLanguage.GetLanguage("My-Language");
typeof(XmlLanguage).GetField("_compatibleCulture", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(language, CultureInfo.CurrentCulture);
this.Language = language;

由于它使用反射,因此不能保证它将来会起作用,但现在它可以(.NET 4.6)。

于 2015-11-26T15:23:32.927 回答
1

我们可以使用 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)));
        }
于 2019-01-10T05:55:34.487 回答
-1

改变后面代码中的语言怎么样?

this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);
于 2012-07-19T09:28:02.823 回答
-1

避免使用“this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);”的问题 不是一个真正的常见的。我不知道法国有任何用户会将日期格式更改为美国或日本格式,因为至少没有用户知道这样的更改是可能的(并且不知道该怎么做)......所以当然“语言=”并不完美,但是在多年的WPF和Silverlight实践中,我从未见过任何用户出现此类问题......所以我仍然使用“语言=”技巧,它很简单并且涵盖100%的真实需求。当然其他解决方案似乎更好,但没有必要(我看到一些与“语言=”解决方案相比远非完美的实现)。

于 2014-08-23T19:08:31.047 回答