LoginSignup
3
3

More than 3 years have passed since last update.

DataGridでAutoGenerateColumnsが有効なままで、フォーマットをカスタムする

Last updated at Posted at 2021-02-13

概要

DataGridでデフォルトのフォーマット以外にしたいことがあります。しかしフォーマットを変えるためだけに、AutoGenerateColumnsを無効にして全ての列を自分で定義するのは面倒です。
1つの解決方法はDataGridのAutoGeneratingColumnイベントでフォーマットを指定することです。
しかしできればコードビハインドを書きたくないし、複数のDataGridで流用したい、そういう時は添付プロパティが使えます。

image.png

添付プロパティ

DateTime用のDateTimeFormatAutoGenerateTimeSpan用のTimeSpanFormatAutoGenerateの2つのフォーマットを指定できる添付プロパティが定義されています。

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;
    }
}

使用方法

XAML上でフォーマットを指定します。
DataGridOperation.DateTimeFormatAutoGenerate="yy年MM月dd日"

コードビハインドは使用していません。

MainWindow.xaml
<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は以下のようになります。

MainWindowViewModel.cs
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;
}

環境

VisualStudio 2019 Version 16.8.4
.NET 5
C#9

参考

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3