当DataGridView的AutoGenerateColumns属性为true时,如何更改DataGridView列的日期格式?

4
我正在根据搜索参数自动生成gridview中的列,其中有几列将被添加或删除。请为我提供一种方法,在gridview的整个列中设置日期格式为dd-mmm-yyyy。
目前,我是使用rowdatabound来完成的。它会检查每一行,因此需要一些时间才能显示结果。
以下是我在rowdatabound中所做的内容:
if (e.Row.RowType == DataControlRowType.DataRow)
{
        System.Data.DataRowView dtview;
        DateTime dt;
        int intCounter;
        dtview = (DataRowView)e.Row.DataItem;

        for (intCounter = 0; intCounter <= dtview.Row.ItemArray.Length - 1; intCounter++)
        {
            if (dtview.Row.ItemArray[intCounter] is System.DateTime)
            {
                dt = (DateTime)dtview.Row.ItemArray[intCounter];
                e.Row.Cells[intCounter].Text = dt.ToString("dd-MMM-yyyy");
            }
        }
    }

这个操作会检查所有记录,然后根据条件进行更改。

但我希望能够做得更好,只需识别列并更改整个列的日期格式即可。


你不能在从数据库返回数据的同时完成吗? - Gowtham.K.Reddy
不,如果我在数据库中这样做,会有一个额外的问题,所以我不这样做。如果我在数据库中这样做,我就无法在网格视图中格式化日期,然后日期就无法分组。 - user2831167
6个回答

1

我有点晚了。但是这对我有用。它仍然使用RowDataBound()方法。但它只针对数据源中的第一行运行。

        protected void gvGridView_RowDataBound(Object sender, GridViewRowEventArgs e)
        {
            DataRowView drv = (DataRowView)e.Row.DataItem;

            if (e.Row.RowType == DataControlRowType.DataRow)
            {

                for (int i = 0; i < ct_columns; i++)
                {
                    DataControlFieldCell dcf = e.Row.Cells[i] as DataControlFieldCell;

                    /* default date format: hide 'time' values */
                    if (e.Row.RowIndex == 0 
                        && (dcf.ContainingField.GetType().Name == "BoundField"           // defined columns
                        || dcf.ContainingField.GetType().Name == "AutoGeneratedField"))  // auto-generated columns 
                    {
                        BoundField bf = dcf.ContainingField as BoundField;

                        if (bf != null && String.IsNullOrEmpty(bf.DataFormatString))
                        {
                            string col_name = bf.DataField;

                            if (!String.IsNullOrEmpty(col_name) && drv[col_name] != null)
                            {
                                if (drv[col_name].GetType().Name == "DateTime")
                                {
                                    // set format for first row
                                    string date = drv[col_name].ToString();
                                    if (!String.IsNullOrEmpty(date))
                                        dcf.Text = DateTime.Parse(date).ToShortDateString();

                                    // set format for other rows
                                    bf.DataFormatString = "{0:M/dd/yyyy}";  
                                }

                            }
                        }
                    }
                }
            }
        }

1

免责声明:我自己没有尝试过,但似乎是可行的。

GridView有一个名为ColumnsGenerator的公共属性,其类型为IAutoFieldGenerator。这是确定如何生成列的对象。

已经有一个实现了IAutoFieldGenerator的对象,即默认的GridViewColumnsGenerator。这是一个公共的、非密封的类,你可以从中派生出一个新的类型。

你需要重写的方法是这个:

public override List<AutoGeneratedField> CreateAutoGeneratedFields(
      object dataObject, Control control);

请注意输出,它是一个AutoGeneratedField的List<T>。 AutoGeneratedField有一个叫做DataFormatString的属性:
public override string DataFormatString { get; set; }

所以你需要做的就是重写CreateAutoGeneratedFields方法,像这样:
public class MyDerivedGridViewColumnsGenerator : GridViewColumnsGenerator
{
   public override List<AutoGeneratedField> CreateAutoGeneratedFields(
      object dataObject, Control control)
   {
       var list = base.CreatedAutoGeneratedFields(dataObject, control);
       foreach(var field in list)
       {
         if(field.DataType == typeof(DateTime))
             field.DataFormatString = "dd-MMM-yyyy";
       }
       return list;
   }
}

现在,我不清楚ColumnsGenerator属性是如何设置的,所以您可能需要在代码中进行设置。但这应该很简单,因为GridViewColumnsGenerator有一个无参数的构造函数:
 // GridView myGridView;
 myGridView.ColumnsGenerator = new MyDerivedGridViewColumnsGenerator();

在绑定到 GridView 之前设置它,这样当创建列时它就已经就位了。


有趣的想法!不幸的是,设置DataFormatString会抛出NotSupportedException异常,而AutoGeneratedField是密封的。 - Piotr Nawrot
@PiotrNawrot 一项美丽的理论被丑陋的事实所摧毁...感谢您的关注!如果您找到了一个优雅的解决方案,请发布出来! - Ann L.
你可能搞混了.NET版本:IAutoFieldGenerator是3.5的,而GridViewColumnsGenerator是在.NET 4.5中实现的。 - Marcel

0
这是一个相当简单的解决方案:不要分别处理每行,而是在绑定网格之前设置列。
在下面的示例中,“view”是一个生成常规“DataTable”的对象,网格视图的“AutoGenerateColumns”属性设置为“false”。
基本上,您只需检查列的数据类型,当它是“DateTime”时,设置所需的格式。
DataTable dt = view.GetReport();

Type dateType = typeof(DateTime);
foreach (DataColumn column in dt.Columns)
{
    BoundField f =  new BoundField();
    f.HeaderText = column.ColumnName;
    f.DataField = column.ColumnName;

    if(column.DataType == dateType)
        f.DataFormatString = "{0:d}"; // Or whatever

    gvReport.Columns.Add(f);
}

gvReport.DataSource = dt;
gvReport.DataBind();

以上代码运行良好(感谢Kevin Shea),但需要在“foreach”语句之前添加gvReport.Volumns.Clear();。如果不这样做,当用户双击或多次单击GridView的重新创建时,将显示越来越多的列。在我的情况下,我让用户添加要在GridView中显示的任何列,并点击一个按钮以显示结果。如果单击“显示结果”按钮超过一次,我会再次重复出现列。 - Lord nick

0

我成功地通过实现DataGridView的ColumnAdded事件来格式化自动生成的日期时间列的值:

    private void dataGridView_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
    {
        if (e.Column.ValueType == typeof(DateTime))
        {
            e.Column.DefaultCellStyle.Format = "dd-MMM-yyyy";
        }
    }

1
看起来你的答案对于DataGridView非常适用,但那是WinForms中的一个控件。这个问题是关于ASP.NET GridView控件的,它没有ColumnAdded事件。 - Doug

0
如果您正在将 DataTable 绑定到 Grid,则可以编写一个扩展方法或链接查询,例如:
public static void ChangeDateFormat<T>(this DataColumn column, Func<object, T> conversion)
{
   foreach(DataRow row in column.Table.Rows)
   {
    row[column] = conversion(row[column]);
   }
}

然后调用那个方法

dataTable.Columns["DateColumanName"].ChangeDateFormat(
val => DateTime.Parse(val.ToString()).ToString("dd/MMM/yyyy"));

从这里提取的实际源代码
还要注意检查列和数据类型的存在以及其他检查,以消除错误。

希望能有所帮助。


-1

使用Eval函数在aspx代码中定义字符串格式:

<% # Eval("Date", "{0:dd-MMM-yyyy}") %>

完整示例:

<asp:TemplateField HeaderText="Date">
    <ItemTemplate>
        <% # Eval("Date", "{0:dd-MMM-yyyy}") %>
    </ItemTemplate>
</asp:TemplateField>

我正在自动生成GridView中的列,所有这些都基于我们在表单中所做的选择。如果用户在其报告中不选择任何日期,该怎么办? - user2831167

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接