This is slightly different wrinkle to the custom date format threads with WPF datagrids.
My Win7 box has a custom short date string defined in the Control Panel as dd-MM-yy. I want a date column in a DataGrid to use that setting for display. The view model has a DateTime called 'Date'.
I tried this:
<DataGrid AutoGenerateColumns="False" Name="dataCondition" ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" ></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Date, StringFormat=d}" />
<DataGridTextColumn Binding="{Binding Comment}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
The date column shows up as m/d/yyyy. Doesn't the DataGrid use the system short date setting, irregardless if it's custom or not?
WPF DatePickers seem to work differently. The custom short date format is used even without a StringFormat (and being bound directly to a DateTime in the view model).
I can get around this problem in the DataGrid by creating a string property in the view model (Date -> DateFormatted) where the getter uses DateTime.ToShortDateString, but I'm not sure this is the best way to do this. And I haven't worked out the binding TwoWay part yet... :P
Create a converter and use it in the binding at the datetime column. A class that inherits IValueConverter. Receives a DateTime and returns a String.
Try setting/binding this as your Converter
:
[ValueConversion(typeof(DateTime), typeof(String))]
public class DateConverter : IValueConverter
{
private const string _format = "dd-MM-yy";
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DateTime date = (DateTime)value;
return date.ToString(_format);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DateTime.ParseExact((string) value, _format, culture);
}
}
Then set up your XAML like this:
<Window.Resources>
<wpfDataGridMisc:DateConverter x:Key="dateConverter"/>
</Window.Resources>
<DataGridTextColumn Binding="{Binding Date, Converter={StaticResource dateConverter}}"/>
I think the solution is rather simple. The StringFormat
you're using is invalid so it gets ignored and DataGridTextColumn
resorts to default format. If you instead specify dd
as StringFormat
, it works as you expect.
so your final binding will look like this (including TwoWay):
<DataGridTextColumn Binding="{Binding Date, StringFormat=dd, Mode=TwoWay}" />
However, please note that this is going to be confusing in edit mode as even though column is showing you just a number (the day) it will actually expect you to write in a valid date before it accepts that input and formats it again as you request it to. You can work around this by using a DataGridTemplateColumn
instead and specifying CellTemplate
and CellEditingTemplate
in there.
This allows you to configure the date time format.
VB Code
Imports System.Windows.Data
Public Class DateTimeToString
Implements IValueConverter
Private _Format As String
Public Property Format() As String
Get
Return _Format
End Get
Set(ByVal value As String)
End Set
End Property
Public Function Convert(ByVal value As Object, _
ByVal targetType As System.Type, _
ByVal parameter As Object, _
ByVal culture As System.Globalization.CultureInfo) As Object _
Implements System.Windows.Data.IValueConverter.Convert
Dim DateTimeValue As DateTime
If DateTime.TryParse(value, DateTimeValue) Then
Return DateTimeValue.ToString(_Format)
End If
Return value
End Function
Public Function ConvertBack(ByVal value As Object, _
ByVal targetType As System.Type, _
ByVal parameter As Object, _
ByVal culture As System.Globalization.CultureInfo) As Object _
Implements System.Windows.Data.IValueConverter.ConvertBack
Dim StringValue As String = value.ToString
Dim DateTimeValue As DateTime
If DateTime.TryParse(StringValue, DateTimeValue) Then
Return DateTimeValue
End If
Return value
End Function
End Class
C# Code
public class DateTimeToString : IValueConverter
{
public string Format { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DateTime DateTimeValue = (DateTime)value;
return DateTimeValue.ToString(Format);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string strValue = value.ToString();
DateTime DateTimeValue;
if (DateTime.TryParse(strValue, out DateTimeValue))
return DateTimeValue;
return value;
}
}
XAML Code
<TextBlock Text="{Binding BirthDate, Converter={StaticResource DateToString}}" />
You have to set the UICulture
when your application starts to what it should be. Then it will use the right formatting from the computer. The XAML resources always default to en-US
you see.