Microsoft Developer Network >
Domovská stránka fór
>
Windows Presentation Foundation (WPF)
>
Data binding localization issue
Data binding localization issue
- Hi everyone!
Have a problem with displaying date with specified format.
For example, we have TextBlock
<TextBlock Name="textBlock1" Text="{Binding}" VerticalAlignment="Top" />
Text property binds on variable:
DateTime d = DateTime.Now;
textBlock1.DataContext = d;
For getting this date in current regional format I'm using next code (in overriden OnStartup method of application):
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))
);
For specifying date in other format we can change culture detail:
CultureInfo culture = new CultureInfo("da-DK");
culture.DateTimeFormat.ShortDatePattern = "d/MMM/yyyy";
culture.DateTimeFormat.DateSeparator = ".";
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
The problem is that it works with simple output (for example: MessageBox.Show(d.ToString()) ) but doesn't change date format in bound UI element (text block in this case)
Všechny reakce
- Hi,
the culture for decoding dates and numbers in controls is determined by their Language property. By setting the default value for Language to Danish, you change all controls on all pages to this culture. If you want to change them again, you have to set their Language property (or their hosting page's Language property) to something else, e.g. through a binding. Changing the culture on the current thread doesn't help in this case.
I suggest that, instead of overriding the default value for the language, you create a property with change notifications somewhere in your application's object model and bind the Language property of every page to this property.
Changes in the Language may not take effect immediately, but only after a control has lost focus and received focus again. If you reload pages after changing the language, or just want to use different languages in different controls, this shouldn't be a problem for you; I just mention it in case you experience the problem. - Thanks for replying hbarck
Actually the issue is with dates formatting in data-bound controls.
We would like to change the default short date pattern for all UI controls that represent dates.
Eventhough we override DateTimeFormat.ShortDatePattern the UI is still showing in default format.
For example, the DateTime.Now.ToString("d") produces "4.Nov.2009" after we change date pattern and set current thread culture.
But UI elements still display "11/4/2009" (default date pattern I guess for the culture that is defined by IetfLanguageTag)
This in an extract from App.xaml.cs that sets the language for all UI elements when applications starts.
protected override void OnStartup(StartupEventArgs e) { Properties.Settings settings = Properties.Settings.Default; CultureInfo culture = new CultureInfo(settings.Locale); culture.DateTimeFormat.ShortDatePattern = "d/MMM/yyyy"; culture.DateTimeFormat.DateSeparator = "."; if (culture != null) { Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = culture; } // Workaround to have all dates, times, numbers bound to UI elements to be presented in the local culture // because by default all UI elements during binding and value converting use the en-US locale FrameworkElement.LanguageProperty.OverrideMetadata( typeof(FrameworkElement), new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag))); base.OnStartup(e); } - Hi,
as I already wrote, changing the culture of the current thread won't help since WPF's controls override it with their own Language attribute. What will help is this:
<Window x:Class="DateFormatTest" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" Title="DateFormatTest" Height="300" Width="300"> <Window.Resources> <s:DateTime x:Key="today">11/4/2009</s:DateTime> </Window.Resources> <StackPanel> <!-- original Language - en-us, since I didn't override the default value for Language --> <TextBlock Text="{Binding Source={StaticResource today}}"/> <!-- changing Language to German, default datetime format --> <TextBlock Language="de-de" Text="{Binding Source={StaticResource today}}"/> <!-- setting Language to German and specifying default format --> <TextBlock Language="de-de"> <TextBlock.Text> <Binding Source="{StaticResource today}" StringFormat="{}{0:d/MMM/yyyy}"/> </TextBlock.Text> </TextBlock> </StackPanel> </Window>
If I understand you right, you want to find a solution that applies to the whole application at once, do you? Well, overriding the default value of Language will set the default date and numeric formats alright, but I don't think you can change the date format to anything except the default date format this way. What you would have to do is to find out where XmlLanguage gets their date formats and override them there, e.g. in the regional settings of the machine. However, I think nobody would like a program to do that to one's computer... So you'll probably have to find a way to apply the custom date format to all the bindings in your application that bind to date values. - Thanks very much for your reply, hbarck.
Yes, you are correct - we wanted to find the solution to apply custom date formatting to the whole application from one place, that wouldn't require changing all controls binding's StringFormat property.
Unfortunately seems we will need to set StringFormat explicitly as you demonstrated for each control. - Hi,
it is possible to change bindings StringFormat during the FrameworkElement.Initialized event, so you could write a general handler for this event and attach it to all your pages, e.g. as an attached behaviour or using a common base class. However, the tricky bit would be to find all the bindings that bind to date properties. I don't have a ready solution for that, but I have a hunch that BindingGroups and a naming convention for properties having date values might help.

