How to add a DatePicker to DataGridTextColumn in WPF
This builds on @Guish's answer but encapsulates it into a new column class.
private void Grid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyType == typeof(DateTime))
{
e.Column = new DataGridDateTimeColumn((DataGridBoundColumn)e.Column);
}
}
internal class DataGridDateTimeColumn : DataGridBoundColumn
{
public DataGridDateTimeColumn(DataGridBoundColumn column)
{
Header = column.Header;
Binding = (Binding)column.Binding;
}
protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
{
var control = new TextBlock();
BindingOperations.SetBinding(control, TextBlock.TextProperty, Binding);
return control;
}
protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
var control = new DatePicker();
control.PreviewKeyDown += Control_PreviewKeyDown;
BindingOperations.SetBinding(control, DatePicker.SelectedDateProperty, Binding);
BindingOperations.SetBinding(control, DatePicker.DisplayDateProperty, Binding);
return control;
}
private void Control_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Return)
{
DataGridOwner.CommitEdit();
}
}
}
I put a DatePicker in every column of my datagrids, here is my helper method that I assign to the DataGrid
in the windows constructor. This method also Cancel generation for complex object that wouldn't show great in the DataGrid.
Adapt as you wish!
public MainWindow()
{
InitializeComponent();
myDataGrid.AutoGeneratingColumn += DataGridUtilities.dataGrid_AutoGeneratingColumn;
}
public static class DataGridUtilities
{
public static void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (!IsTypeOrNullableOfType(e.PropertyType, typeof(string))
&& !IsNullableOfValueType(e.PropertyType))
{
e.Cancel = true;
}
else if (IsTypeOrNullableOfType(e.PropertyType, typeof (DateTime)))
{
DataGridTemplateColumn col = new DataGridTemplateColumn();
col.Header = e.Column.Header;
FrameworkElementFactory datePickerFactoryElem = new FrameworkElementFactory(typeof (DatePicker));
Binding dateBind= new Binding(e.PropertyName);
dateBind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
dateBind.Mode = BindingMode.TwoWay;
datePickerFactoryElem.SetValue(DatePicker.SelectedDateProperty, dateBind);
datePickerFactoryElem.SetValue(DatePicker.DisplayDateProperty, dateBind);
DataTemplate cellTemplate = new DataTemplate();
cellTemplate.VisualTree = datePickerFactoryElem;
col.CellTemplate = cellTemplate;
e.Column = col;//Set the new generated column
}
}
private static bool IsTypeOrNullableOfType(Type propertyType, Type desiredType)
{
return (propertyType == desiredType || Nullable.GetUnderlyingType(propertyType) == desiredType);
}
private static bool IsNullableOfValueType(Type propertyType)
{
return (propertyType.IsValueType ||
(Nullable.GetUnderlyingType(propertyType) != null &&
Nullable.GetUnderlyingType(propertyType).IsValueType));
}
}
As Nitesh said, use DataGridTemplateColumn
<DataGridTemplateColumn Header="Pick a Date">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding myDate}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<DatePicker SelectedDate="{Binding myDate}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>