Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My DateTime format changes when binding

Tags:

c#

datetime

wpf

I'm based in the UK, and my computer always shows a UK date format (dd/mm/yyyy).

My WPF project is, for some reason converting my DateTime format to US type. This occurs on my work machine and home machine.

I've been able to replicate the issue very simply

<Window x:Class="TimeIssues.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <TextBlock Text="{Binding MyTime}"></TextBlock> <!-- the value is 1/28/2014 10:15:37 (note it is M/dd/yyyy....)
</Grid>
</Window>

And in the code behind, simply

public partial class MainWindow : Window
{
    public MainWindow()
    {
        SetMyTime("28/01/2014 10:15:37"); //note, this is dd/MM/yyyy .... format
        this.DataContext = this;
        InitializeComponent();
    }

    private void SetMyTime(string dateTime)
    {
        DateTime dt;
        DateTime.TryParseExact(dateTime, "dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
        MyTime = dt; // the value is expected, showing 28/01/2014 10:15:37
    }

    public DateTime MyTime { get; set; }
}

Just to confirm that this isn't an IT issue (or so I think), my PC is set for UK (and the Location is also set to UK as is the Current language for non-unicode programs)

enter image description here

I have read WPF format DateTime in TextBlock? but this won't help (I don't think) as that question is about setting the format when the format is known.

If I update my MyTime from DateTime to a string, then the result is expected (UK format)! The issue is WPF changes the format when the type is DateTime which is not desired!

My issue is 2 fold -

  1. I won't know the format the user needs (my software is distributed world wide).
  2. WPF appears to change the format incorrectly any way!

How do I tell WPF to use the user's locale settings? Is there any way to read the OS settings (as per the screen shot above)?

like image 371
Dave Avatar asked Mar 15 '14 14:03

Dave


People also ask

What is the default format of DateTime?

Datetime data types are used to store date and time information. The DATE data type consists of year, month, and day information to represent a date value. The default format for the DATE data type is YYYY-MM-DD. YYYY represents the year, MM represents the month, and DD represents the day.

How do I convert a DateTime to a specific format?

The ToString() method of the DateTime class is used to convert a DateTime date object to string format. The method takes a date format string that specifies the required string representation.

How to set format DateTime in c#?

ParseExact(dateLiteral, "d", new CultureInfo("en-US")); var dateLiteral = "8/24/2017"; var date = DateTime. ParseExact(dateLiteral, "d", new CultureInfo("en-US")); Here we use the short date standard format specifier d to parse a string literal.

What is ddd in date format?

The "ddd" custom format specifier represents the abbreviated name of the day of the week. The localized abbreviated name of the day of the week is retrieved from the DateTimeFormatInfo.AbbreviatedDayNames property of the current or specified culture.


1 Answers

CultureInfo is picked from Thread's current culture which in your case will be set to en-US. You need to set it to en-GB like this:

Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-GB");

But when you set this you will see, XAML doesn't pick this. For XAML to pick it you have to override FrameworkElement.LanguageProperty metadata.

Override OnStartup() method in your App.xaml.cs and place this code there and you are good to go:

protected override void OnStartup(StartupEventArgs e)
{
   base.OnStartup(e);

   Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-GB");
   Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-GB");

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

UPDATE

Is there any way to read the OS settings (as per the screen shot above)?

In case you want to pick CultureInfo based on the format selected for system, you can do that as well by getting LCID for OS. This is how you do it:

[DllImport("kernel32.dll")]
private static extern int GetUserDefaultLCID();

protected override void OnStartup(StartupEventArgs e)
{
   base.OnStartup(e);

   int machineLCID = GetUserDefaultLCID();
   CultureInfo machineCultureInfo = CultureInfo.GetCultureInfo(machineLCID);
   Thread.CurrentThread.CurrentUICulture = machineCultureInfo;
   Thread.CurrentThread.CurrentCulture = machineCultureInfo;

   FrameworkElement.LanguageProperty.OverrideMetadata(
                typeof(FrameworkElement),
                new FrameworkPropertyMetadata(
           XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
}
like image 150
Rohit Vats Avatar answered Sep 22 '22 01:09

Rohit Vats