2009-07-16 31 views
5

Estoy creando un GridView en un método de este modo:Cambio de propiedades de la columna de GridView de código subyacente

GridView gridView = new GridView(); 
gridView.DataSource = reportData.Tables[0]; 
gridView.DataBind(); 

tarde estoy exportarlo a Excel y funciona muy bien. Las columnas se generan automáticamente a partir de mis datos de origen. Me gustaría cambiar la propiedad DataFormatString de algunas de las columnas, sin embargo, después de la databind y antes de exportar a Excel. Parece que no puedo encontrar la propiedad correcta para cambiar. ¿Alguien puede señalarme en la dirección correcta?

Respuesta

7

Según AutoGenerateColumns documentation:

Esta opción proporciona una manera conveniente para mostrar todos los campos en los datos de origen; sin embargo, tiene control limitado de cómo se muestra automáticamente un campo de columna generado o se comporta.

Nota: Automáticamente campos generados columna dependiente no están añadido a la colección Columns.

Estoy cansado de buscar estos AutoGeneratedField s sin suerte.
puedo pensar en varias opciones para lograr que (de peor a mejor):

  1. añadir un evento a la red (como RowDataBound), esto le dará acceso a las células de las filas, pero no es muy conveniente.
  2. No utilice AutoGeneratedField crear estas columnas manualmente, como en:

    BoundField dateField = new BoundField(); 
    dateField.HeaderText = "Date"; 
    dateField.DataField = "date"; 
    dateField.DataFormatString = "{0:MMMM, yyyy}"; 
    gridView.Columns.Add(dateField); 
    

    Esta opción le da control sobre los títulos bes.

  3. Agregue otra capa para el formato de datos y la presentación. Esta es probablemente la mejor opción. Además, de esa manera no tiene que usar DataTables, un GridView puede vincularse a cualquier colección de objetos con propiedades públicas (por ejemplo, a un List<Employee)) y AutoGeneratedField los convierte en columnas.
    Creo que esta es la mejor opción. Supongamos que puede acceder a las columnas automáticas, ¿entonces qué? Tendría que buscar una columna basada en su nombre o índice, lo que parece muy desordenado, y aumenta el acoplamiento.

Y, como última nota, debe pensar en crear archivos de Excel mediante la API. No es tan fácil, pero los archivos HTML XLS son menos compatibles con Excel 2007: muestra un mensaje de advertencia de que el formato del archivo es incompatible con la extensión y, lo que es peor, el archivo se bloquea si se abre y se guarda (aunque puede ser Save As)), lo que hace que sus archivos sean menos fáciles de usar.

+0

El uso de la API requiere que Excel esté instalado en el servidor ... ¿correcto? –

+0

Creo que sí, si está usando interoperabilidad de oficina. Si crea archivos xlsx (of office 2007), básicamente son un grupo de archivos XML comprimidos, por lo que puede crearlos con relativa facilidad (mejor: encuentre una biblioteca). También puede escribir en Excel a través de una cadena de conexión y ole db. La forma más simple, por cierto (aunque sin formatear), es crear un archivo CSV. – Kobi

+0

No puedo instalar Excel en el servidor. No puedo usar los archivos xlsx porque tienen que ser compatibles con 2000 y 2003. Se requiere formato, por lo que no puedo usar csv. Creo que puedo probar tu segunda sugerencia arriba y veré cómo funciona. ¡Gracias! –

-1

Este es el problema de cómo funciona asp.net. Cuando crea algunos controles (columnas) en un método y establece este conjunto de controles en usuario, la próxima vez que la publicación del usuario le devuelva datos, no tendrá acceso a esas columnas, ya que ... no existen. Cada vez que visualiza su sitio, se crea un nuevo objeto (instancia).
La única manera de ser capaz de obtener los datos en post de vuelta de los controles creados anteriormente es crear controles en el método Page_Init ...

+0

No estoy seguro de que comprenda lo que estoy tratando de hacer aquí. Estoy creando una instancia de la cuadrícula en el código para exportar inmediatamente a Excel. La devolución de datos no es un problema. –

0

Por ejemplo:

String newDataFormatString = "{0:d}"; 
BoundField bf = gridView.Columns[Index] as BoundField; 
if (bf != null) { 
    bf.DataFormatString = "{0}"; // workaround to sync with ViewState (it's documented) 
    bf.DataFormatString = newDataFormatString; 
} 
+0

Parece que al usar AutoGenerateColumns, la colección Columns está vacía, aunque el resultado final sí tiene columnas. –

-1

He aquí un extracto de un exportador GridView escribí que convierte controles en un GridView en literales que son reformateados. Podría ser de alguna ayuda:

 /// <summary> 
    /// Parses and cleans up data from the GridView controls collection 
    /// to make the data more suitable for Exported 
    /// </summary> 
    /// <param name="gv">The GridView to parse</param> 
    private void CleanUpControls(Control gv) 
    { 
     Literal l = new Literal(); 

     for (int i = 0; i < gv.Controls.Count; i++) 
     { 

      if (gv.Controls[i].GetType() == typeof (LinkButton)) 
      { 
       l.Text = (gv.Controls[i] as LinkButton).Text; 
       ReplaceWithLiteral(gv, l, i); 
      } 
      else if (gv.Controls[i].GetType() == typeof (ListControl)) 
      { 
       l.Text = (gv.Controls[i] as ListControl).SelectedItem.Text; 
       ReplaceWithLiteral(gv, l, i); 
      } 
      else if (gv.Controls[i].GetType() == typeof (CheckBox)) 
      { 
       l.Text = (gv.Controls[i] as CheckBox).Checked ? "True" : "False"; 
       ReplaceWithLiteral(gv, l, i); 
      } 
      else if (gv.Controls[i].GetType() == typeof (BooleanImage)) 
      { 
       l.Text = (gv.Controls[i] as BooleanImage).Value ? "True" : "False"; 
       ReplaceWithLiteral(gv, l, i); 
      } 
      else if (gv.Controls[i].GetType().ToString() == "System.Web.UI.WebControls.PagerTable") 
       ReplaceWithLiteral(gv, l, i); 

      else if (gv.Controls[i].GetType() == typeof (HyperLink)) 
      { 
       HyperLink hl = gv.Controls[i] as HyperLink; 
       if (MakeHyperLinksAbsolute) 
       { 
        if (hl != null) 
         hl.NavigateUrl = UrlHelper.MakeAbsoluteUrl(hl.NavigateUrl); 
       } 

       switch (TreatHyperLinksAs) 
       { 
        case HyperLinkMode.Text: 
         l.Text = hl.Text; 
         ReplaceWithLiteral(gv, l, i); 
         break; 

        case HyperLinkMode.NavigateUrl: 
         if (hl != null) l.Text = hl.NavigateUrl; 
         ReplaceWithLiteral(gv, l, i); 
         break; 

        case HyperLinkMode.ToolTip: 
         l.Text = hl.ToolTip; 
         ReplaceWithLiteral(gv, l, i); 
         break; 

        case HyperLinkMode.TextAndLink: 
         l.Text = String.Format("{0} ({1})", hl.Text, hl.NavigateUrl); 
         ReplaceWithLiteral(gv, l, i); 
         break; 

        case HyperLinkMode.HyperLink: 
         break; 
       } 
      } 

      if (gv.Controls[i].HasControls()) 
       CleanUpControls(gv.Controls[i]); 
     } 
    } 
+0

Esto realmente no ayuda en el contexto de mi pregunta. Estoy seguro de que es útil para otras aplicaciones. –

Cuestiones relacionadas