如何在WPF中向DataGridTextColumn添加一个DatePicker

时间:2020-12-13 07:28:02
<DataGrid Name="myfirstdg"
          Grid.Row="2"
          AutoGenerateColumns="False"
          CanUserSortColumns="False"
          CanUserAddRows="False"
          CanUserDeleteRows="False"
          SelectionUnit="Cell">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Date"
                            Binding="{Binding Path=date}"
                            Width="SizeToCells"
                            IsReadOnly="True"
                            MinWidth="100"/>
    </DataGrid.Columns>
</DataGrid>

I have a simple DataGrid with a DataGridTextColumn in it. How do I add a Datepicker to my DataGridTextColumn?

我有一个简单的DataGrid,其中包含一个DataGridTextColumn。如何向DataGridTextColumn添加一个Datepicker ?

3 个解决方案

#1


22  

As Nitesh said, use DataGridTemplateColumn

正如尼泰什所说,使用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>

#2


4  

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.

我在DataGrid的每一列中都放了一个DatePicker,这是我在windows构造函数中分配给DataGrid的助手方法。该方法还取消了在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));
    }
}

#3


1  

This builds on @Guish's answer but encapsulates it into a new column class.

这基于@Guish的答案,但将其封装到一个新的列类中。

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();
        BindingOperations.SetBinding(control, DatePicker.SelectedDateProperty, Binding);
        BindingOperations.SetBinding(control, DatePicker.DisplayDateProperty, Binding);
        return control;
    }
}

#1


22  

As Nitesh said, use DataGridTemplateColumn

正如尼泰什所说,使用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>

#2


4  

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.

我在DataGrid的每一列中都放了一个DatePicker,这是我在windows构造函数中分配给DataGrid的助手方法。该方法还取消了在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));
    }
}

#3


1  

This builds on @Guish's answer but encapsulates it into a new column class.

这基于@Guish的答案,但将其封装到一个新的列类中。

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();
        BindingOperations.SetBinding(control, DatePicker.SelectedDateProperty, Binding);
        BindingOperations.SetBinding(control, DatePicker.DisplayDateProperty, Binding);
        return control;
    }
}