WPF datagrid date column with system custom short

2019-07-20 23:50发布

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

5条回答
放荡不羁爱自由
2楼-- · 2019-07-21 00:42

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.

查看更多
Anthone
3楼-- · 2019-07-21 00:43

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.

查看更多
再贱就再见
4楼-- · 2019-07-21 00:46

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}}"/>
查看更多
太酷不给撩
5楼-- · 2019-07-21 00:48

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.

查看更多
手持菜刀,她持情操
6楼-- · 2019-07-21 00:55

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}}" />
查看更多
登录 后发表回答