65

I want to change is the date column from a format "DD/MM/YYYY HH:MM:SS" to "DD.MM.YYYY".

  <DataGrid Name="dgBuchung" AutoGenerateColumns="True" 
            ItemsSource="{Binding}" Grid.ColumnSpan="3" >
  <ab:DataGridTextColumn Header="Fecha Entrada" Width="110"  
       Binding="{Binding date, StringFormat={}{0:dd/MM/yyyy}}" IsReadOnly="True" />
                        
</DataGrid>
                                      

Unfortunately that code throws an XMLParseException.

First of all, is this way of solution possible while using AutoGenerateColumns? If no, how else can I try to handle this?

If yes, what is the problem with the code above?

ΩmegaMan
  • 22,885
  • 8
  • 76
  • 94
Harald
  • 731
  • 3
  • 10
  • 15

7 Answers7

122

Don`t forget to use DataGrid.Columns, all columns must be inside that collection. In my project I format date a little bit differently:

<tk:DataGrid>
    <tk:DataGrid.Columns>
        <tk:DataGridTextColumn Binding="{Binding StartDate, StringFormat=\{0:dd.MM.yy HH:mm:ss\}}" />
    </tk:DataGrid.Columns>
</tk:DataGrid>

With AutoGenerateColumns you won`t be able to contol formatting as DataGird will add its own columns.

icebat
  • 4,560
  • 4
  • 20
  • 35
  • Ok, thank you for that! Is it possible to bind a Column to a field out of my database without having a property in my project? – Harald Nov 02 '11 at 10:12
  • 1
    @Harald, no, you cant bind directly to database field, first you have to make or generate some object (for example, using [Entity Framework](http://msdn.microsoft.com/en-us/library/bb386876.aspx)). If you already have a collection of such objects, then you can bind it to DataGrid.ItemsSource property, as you did in your code. – icebat Nov 02 '11 at 10:28
  • Thanks a lot ! This post saved me ! – chinthana Sep 03 '14 at 08:06
  • If StringFormat depends of Culture? For sample, En-US : dd.MM.yy , FR : dd-MM-yyyy, ES-es: dd/MM/yyyy, etc – Kiquenet Sep 17 '14 at 08:48
  • 1
    @Kiquenet, if you have some custom format for every culture then you better move that logic to Converter or property getter. Otherwise you can look into some more options with [custom date formatting](http://msdn.microsoft.com/en-us/library/8kb3ddd4%28v=vs.110%29.aspx) – icebat Sep 17 '14 at 08:59
  • Converter or property getter samples ? _IMHO, better samples for minimize learning curve are real applications with full source code and good patterns_ – Kiquenet Sep 19 '14 at 11:52
  • What is that zero character doing in the string format? It's needed but I can't really figure out why. When I format normal strings in C# I usuall go *dateTime.ToString("dd MMM")* to get "08 Jul". But here it seems to be different and I'm unsure what to google for... – Konrad Viltersten Aug 07 '15 at 14:17
  • 1
    @KonradViltersten, it's an index for [string.Format](https://msdn.microsoft.com/en-us/library/system.string.format%28v=vs.110%29.aspx) that is used when [StringFormat](https://msdn.microsoft.com/en-us/library/system.windows.data.bindingbase.stringformat%28v=vs.110%29.aspx) is applied. – icebat Aug 10 '15 at 16:03
  • Like Terrence answered below, use {Binding StartDate, StringFormat=d} to use user's Short Date format. – Gordon Bell Jan 06 '17 at 23:03
104

Very late to the party here but in case anyone else stumbles across this page...

You can do it by setting the AutoGeneratingColumn handler in XAML:

<DataGrid AutoGeneratingColumn="OnAutoGeneratingColumn"  ..etc.. />

And then in code behind do something like this:

private void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.PropertyType == typeof(System.DateTime))
        (e.Column as DataGridTextColumn).Binding.StringFormat = "dd/MM/yyyy";
}
Mark Feldman
  • 13,965
  • 2
  • 24
  • 47
  • That's cool, I like that I'm loading data from a text file and setting the types as I go. – MikeAinOz Nov 22 '14 at 09:43
  • 2
    Great! In case you need a VB.NET version: Private Sub MyGrid_AutoGeneratingColumn(sender As Object, e As DataGridAutoGeneratingColumnEventArgs) handles MyGrid.AutoGeneratingColumn If e.PropertyType = GetType(System.DateTime) Then TryCast(e.Column, DataGridTextColumn).Binding.StringFormat = "dd/MM/yyyy" End If End Sub – Andrea Antonangeli Sep 22 '15 at 10:24
  • Great way to use autogeneratecolumns – cdie Feb 16 '16 at 08:06
  • (e.Column as DataGridTextColumn).Binding.StringFormat = "d"; // use Short Date format – Gordon Bell Jan 06 '17 at 23:08
  • Format date columns differently using e.PropertyName: if (e.PropertyName == "Open_Date") {(e.Column as DataGridTextColumn).Binding.StringFormat = "d";} – Gordon Bell Jan 06 '17 at 23:10
  • you are a hero :) that was exactly what i was searching for. though you won't have to add single collumns with bindings. – LuckyLikey Mar 15 '17 at 09:47
  • 3
    I would use `DataGridBoundColumn` instead of `DataGridTextColumn` to be more generic. – JohnyL Nov 09 '18 at 16:44
16

If your bound property is DateTime, then all you need is

Binding={Property, StringFormat=d}
Terence
  • 557
  • 4
  • 7
4
Binding="{Binding YourColumn ,StringFormat='yyyy-MM-dd'}"
pushkin
  • 7,514
  • 14
  • 41
  • 74
2

first select datagrid and then go to properties find Datagrid_AutoGeneratingColumn and the double click And then use this code

   Datagrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
            {
                if (e.PropertyName == "Your column name")
                    (e.Column as DataGridTextColumn).Binding.StringFormat = "dd/MMMMMMMMM/yyyy";
                if (e.PropertyName == "Your column name")
                    (e.Column as DataGridTextColumn).Binding.StringFormat = "dd/MMMMMMMMM/yyyy";
            }

I try it it works on WPF

  • Although I'm using Mark Feldman for my project, your solution is very useful for those cases when you have different properties of the same type and you want different formats for each one. – Antonio Rodríguez May 21 '21 at 08:16
1

I know the accepted answer is quite old, but there is a way to control formatting with AutoGeneratColumns :

First create a function that will trigger when a column is generated :

<DataGrid x:Name="dataGrid" AutoGeneratedColumns="dataGrid_AutoGeneratedColumns" Margin="116,62,10,10"/>

Then check if the type of the column generated is a DateTime and just change its String format to "d" to remove the time part :

private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            if(YourColumn == typeof(DateTime))
            {
                e.Column.ClipboardContentBinding.StringFormat = "d";
            }
        }
Treycos
  • 6,780
  • 3
  • 19
  • 36
0

This is a very old question, but I found a new solution, so I wrote about it.

First of all, is this way of solution possible while using AutoGenerateColumns?

Yes, that can be done with AttachedProperty as follows.

<DataGrid AutoGenerateColumns="True" 
   local:DataGridOperation.DateTimeFormatAutoGenerate="yy-MM-dd"
   ItemsSource="{Binding}" />

AttachedProperty

There are two AttachedProperty defined that allow you to specify two formats. DateTimeFormatAutoGenerate for DateTime and TimeSpanFormatAutoGenerate for TimeSpan.

class DataGridOperation
{
    public static string GetDateTimeFormatAutoGenerate(DependencyObject obj) => (string)obj.GetValue(DateTimeFormatAutoGenerateProperty);
    public static void SetDateTimeFormatAutoGenerate(DependencyObject obj, string value) => obj.SetValue(DateTimeFormatAutoGenerateProperty, value);
    public static readonly DependencyProperty DateTimeFormatAutoGenerateProperty =
        DependencyProperty.RegisterAttached("DateTimeFormatAutoGenerate", typeof(string), typeof(DataGridOperation),
            new PropertyMetadata(null, (d, e) => AddEventHandlerOnGenerating<DateTime>(d, e)));

    public static string GetTimeSpanFormatAutoGenerate(DependencyObject obj) => (string)obj.GetValue(TimeSpanFormatAutoGenerateProperty);
    public static void SetTimeSpanFormatAutoGenerate(DependencyObject obj, string value) => obj.SetValue(TimeSpanFormatAutoGenerateProperty, value);
    public static readonly DependencyProperty TimeSpanFormatAutoGenerateProperty =
        DependencyProperty.RegisterAttached("TimeSpanFormatAutoGenerate", typeof(string), typeof(DataGridOperation),
            new PropertyMetadata(null, (d, e) => AddEventHandlerOnGenerating<TimeSpan>(d, e)));

    private static void AddEventHandlerOnGenerating<T>(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is DataGrid dGrid))
            return;

        if ((e.NewValue is string format))
            dGrid.AutoGeneratingColumn += (o, e) => AddFormat_OnGenerating<T>(e, format);
    }

    private static void AddFormat_OnGenerating<T>(DataGridAutoGeneratingColumnEventArgs e, string format)
    {
        if (e.PropertyType == typeof(T))
            (e.Column as DataGridTextColumn).Binding.StringFormat = format;
    }
}

How to use

View

<Window
   x:Class="DataGridAutogenerateCustom.MainWindow"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local="clr-namespace:DataGridAutogenerateCustom"
   Width="400" Height="250">
   <Window.DataContext>
      <local:MainWindowViewModel />
   </Window.DataContext>
   <StackPanel>
      <TextBlock Text="DEFAULT FORMAT" />
      <DataGrid ItemsSource="{Binding Dates}" />

      <TextBlock Margin="0,30,0,0" Text="CUSTOM FORMAT" />
      <DataGrid
         local:DataGridOperation.DateTimeFormatAutoGenerate="yy-MM-dd"
         local:DataGridOperation.TimeSpanFormatAutoGenerate="dd\-hh\-mm\-ss"
         ItemsSource="{Binding Dates}" />
   </StackPanel>
</Window>

ViewModel

public class MainWindowViewModel
{
    public DatePairs[] Dates { get; } = new DatePairs[]
    {
        new (){StartDate= new (2011,1,1), EndDate= new (2011,2,1) },
        new (){StartDate= new (2020,1,1), EndDate= new (2021,1,1) },
    };
}

public class DatePairs
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public TimeSpan Span => EndDate - StartDate;
}

demo_wpf_datagrid

soi
  • 1
  • 1