Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用「;“真正的”;CultureInfo.CurrentCulture位于WPF绑定中,而不是IETGatag中的CultureInfo_C#_Wpf_Binding_Currentculture - Fatal编程技术网

C# 使用「;“真正的”;CultureInfo.CurrentCulture位于WPF绑定中,而不是IETGatag中的CultureInfo

C# 使用「;“真正的”;CultureInfo.CurrentCulture位于WPF绑定中,而不是IETGatag中的CultureInfo,c#,wpf,binding,currentculture,C#,Wpf,Binding,Currentculture,就我而言: 我有一个TextBlock绑定到DateTime类型的属性。 我希望它显示为用户所说的区域设置 <TextBlock Text="{Binding Date, StringFormat={}{0:d}}" /> 但是使用这行代码,它只是将文本显示为CultureInfo的默认格式 CurrentCulture的IetfLanguageTag表示,与系统区域设置中选择的有效值不同: (例如,对于“de de”dd.MM.yyyyy用于代替所选的yyyy-MM-dd) 有

就我而言:

我有一个TextBlock绑定到DateTime类型的属性。 我希望它显示为用户所说的区域设置

<TextBlock Text="{Binding Date, StringFormat={}{0:d}}" />
但是使用这行代码,它只是将文本显示为CultureInfo的默认格式 CurrentCulture的IetfLanguageTag表示,与系统区域设置中选择的有效值不同:

(例如,对于“de de”dd.MM.yyyyy用于代替所选的yyyy-MM-dd

有没有一种方法可以使绑定使用正确的格式而不在每个绑定上定义ConverterCulture

编码

string.Format("{0:d}",Date);
使用正确的区域性设置

编辑:

另一种不按预期工作的方式(如.Language=…所做的):


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


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


如果你需要更多的帮助,请告诉我

您的第二次尝试很接近,并引导我找到了一个对我来说确实有效的解决方案

设置ConverterCulture的问题在于,它仅在拥有转换器时使用。因此,只需创建一个简单的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”)


如何更改代码后面的Lanague

this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);

这是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) CultureWareBinding的实际使用

<Textblock Text="{myWpfLib:CultureAwareBinding Path=Salary, Source=Contact, StringFormat={}{0:C}}" />

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

我使用这些代码,并根据自己的需要获得适当的结果。希望它能填满你的:-)! 如果不能“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>

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

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

由于它使用的是反射,因此不能保证它将来会工作,但目前它确实工作(.NET 4.6)。

在初始化任何UI之前,请先输入以下代码行。这对我有用

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

(并删除所有显式区域性参数)

我们可以使用IValueConverter创建日期时间转换器

[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)));
        }
//
///集合培养
/// 
私有void SetCulture(){
var newCulture=newcultureinfo(“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(类型为(FrameworkElement)),新FrameworkPropertyMetadata(
System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag));
}

查看以下内容:@Pavlo:此问题的答案还使用IetfLanguageTag获取文化信息。谢谢您的回答。这个解决方案听起来像是唯一一个可能的解决方案。“因为追溯性地强制绑定尊重文化可能会破坏WPF中依赖于这种行为的其他代码。”-我认为,从长远来看,继续保持这种破坏的行为比引入短期中断更糟糕。或者,他们可以修复它,但使用.NET的程序集绑定功能来检测应用程序何时需要较旧的版本,并为其维护已损坏的行为。这个bug在WPF中已经存在了12年,而且他们没有自己的
CultureAwareBinding
内置,这真是太疯狂了。这个方法忽略了“区域和语言”对话框中的自定义设置,只使用名称来获取语言。这是最简单的解决方案,对我来说也很好(Windows Phone 7)@Markus k:对不起,没听清楚你想说什么/解释什么?@hfmobile他的意思是,如果你在区域设置(德国除外)中选择一种语言,然后手动修改任何设置(例如短日期更改为d.M.yyyy),则设置上述建议的语言将不会生效
FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement),
    new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
[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();
        }


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