c# - por - Cómo cambiar el formato de fecha de la columna datagridview cuando gridview tiene autogeneratecolumns=true
dar formato a un datagridview c# (6)
Estoy auto generando columnas en gridview dependiendo de los parámetros de búsqueda, se agregarán o eliminarán pocas columnas.
Por favor sugiérame una forma de establecer el formato de fecha a dd-mmm-yyyy
para toda la columna en gridview.
Por ahora, lo hago usando rowdatabound
. Verifica cada fila, por lo que lleva tiempo mostrar los resultados.
Esto es lo que hago en 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");
}
}
}
Esto verifica todos los registros y luego los cambios en función de la condición.
Pero quiero hacerlo mejor, simplemente identificando la columna y cambiando el formato de fecha para la columna completa.
Aquí hay una solución bastante simple: en lugar de manejar cada fila por separado, configure las columnas antes de enlazar la grilla.
En el siguiente ejemplo, view
es un objeto que genera una DataTable
normal y la vista de cuadrícula tiene su propiedad AutoGenerateColumns
establecida en false
.
Esencialmente, solo examina el tipo de datos de las columnas y cuando es un DateTime
, configure el formato que desee.
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();
Descargo de responsabilidad: No lo he intentado yo mismo, pero parece posible.
Un GridView
tiene una propiedad pública llamada ColumnsGenerator
que tiene un tipo de IAutoFieldGenerator
. Este es el objeto que determina cómo se generan las columnas.
Ya existe una implementación de IAutoFieldGenerator
, la predeterminada: GridViewColumnsGenerator
. Esta es una clase pública, no sellada, y puedes derivar un tipo de ella.
El método que debe sobrescribir es este:
public override List<AutoGeneratedField> CreateAutoGeneratedFields(
object dataObject, Control control);
Tenga en cuenta la salida, una lista <T> de AutoGeneratedField
. AutoGeneratedField
tiene una propiedad llamada DataFormatString
:
public override string DataFormatString { get; set; }
Entonces, todo lo que tendrías que hacer es anular CreateAutoGeneratedFields
, así:
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;
}
}
Ahora, no tengo claro cómo se establece la propiedad ColumnsGenerator
, por lo que podría tener que hacerlo en el código. Pero eso debería ser bastante simple, ya que GridViewColumnsGenerator
tiene un constructor sin parámetros:
// GridView myGridView;
myGridView.ColumnsGenerator = new MyDerivedGridViewColumnsGenerator();
Lo configuraría antes de vincularlo a GridView
, de modo que esté en su lugar cuando sea el momento de crear las columnas.
Estoy un poco tarde. Pero esto funcionó para mí. Todavía usa el método RowDataBound (). Pero solo se ejecuta contra la primera fila en la fuente de datos.
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}";
}
}
}
}
}
}
}
Logré formatear los valores de una columna de fecha y hora generada automáticamente implementando el evento ColumnAdded de DataGridView:
private void dataGridView_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
if (e.Column.ValueType == typeof(DateTime))
{
e.Column.DefaultCellStyle.Format = "dd-MMM-yyyy";
}
}
Use la función Eval
para definir la formación de cadenas en el código aspx:
<% # Eval("Date", "{0:dd-MMM-yyyy}") %>
Ejemplo completo:
<asp:TemplateField HeaderText="Date">
<ItemTemplate>
<% # Eval("Date", "{0:dd-MMM-yyyy}") %>
</ItemTemplate>
</asp:TemplateField>
si está vinculando una DataTable a Grid, escriba un método de extensión o enlace Query como
public static void ChangeDateFormat<T>(this DataColumn column, Func<object, T> conversion)
{
foreach(DataRow row in column.Table.Rows)
{
row[column] = conversion(row[column]);
}
}
Y llamar a ese Método
dataTable.Columns["DateColumanName"].ChangeDateFormat(
val => DateTime.Parse(val.ToString()).ToString("dd/MMM/yyyy"));
Código fuente real extraído de aquí
Y también tenga en cuenta que necesita verificar la existencia de columna y tipo de datos y las otras verificaciones para deshacerse de los errores.
Espero eso ayude.