2009-06-03 15 views
8

Tengo un sitio web asp.net bastante grande que usa GridView vinculado al mismo objeto en muchos lugares. Estoy usando una plantilla de elemento para personalizar cada fila. Sin embargo, para tener la misma plantilla en todas las páginas tengo que copiar & pegar la plantilla del elemento en cada página. Obviamente esta no es la mejor solución. Además de esto, quiero poder cambiar la plantilla utilizada por GridView, cambiando algún archivo de configuración. Una opción sería crear un control de usuario con DataGrid y exponer las propiedades necesarias para usar en cada página. Sin embargo, esto no cumple con el segundo requisito para poder cambiar dinámicamente la plantilla. Básicamente estoy buscando una forma de decirle a GridView que use una plantilla y pueda hacer esto de forma dinámica. Cualquier idea sería útil.Cambie dinámicamente plantilla de elemento GridView

+0

¿quieres cambiar la plantilla porque tienes una plantilla de diseño diferente? –

+0

sí, quiero tener diferentes plantillas de diseño y poder cambiarlas dinámicamente – Albert

Respuesta

9

Con el fin de lograr lo que desea, usted tiene dos opciones como lo veo:

1.) Construir cada TemplateField dinámicamente en el código, y activa estas basado en alguna configuración.
2.) Cree controles de usuario para sus cuadrículas personalizadas y utilícelos en su lugar.

Sé que usted dijo que no desea usar un UserControl porque eso le quitará la capacidad de cambiar dinámicamente su diseño, pero permítanme cuestionar esa presuposición con un ejemplo.

Puede utilizar las funciones incorporadas de ASP.Net para cambiar dinámicamente los controles de usuario a su gusto utilizando un PlaceHolder Control.

<asp:PlaceHolder ID="GridViewPlaceHolder" runat="server" /> 

Sus rejillas personalizados pueden ser construidos de forma declarativa en .ascx y luego cargados en su lugar de forma dinámica en tiempo de ejecución, así:

GridViewPlaceHolder.Controls.Add(LoadControl("~/Controls/MyCustomControl.ascx")); 

Ahora, si realmente desea hacer su vida más fácil, entonces puede crear una clase base abstracta de la que heredarán todos sus controles de cuadrícula personalizados. De esta forma, sus controles pueden tratarse genéricamente cuando se cargan.

public abstract class CustomGridControl: System.Web.UI.UserControl 
{ 
    public abstract Object DataSource { get; set; } 
} 

Un simple rejilla se puede definir en el marcado:

<asp:GridView ID="myGridView" runat="server" AutoGenerateColumns="false"> 
    <Columns> 
     <asp:TemplateField HeaderText="Name"> 
      <ItemTemplate> 
       <asp:Label Text='<%#Eval("Name") %>' runat="server"></asp:Label> 
      </ItemTemplate> 
     </asp:TemplateField> 
     <asp:TemplateField HeaderText="Age"> 
      <ItemTemplate> 
       <asp:Label Text='<%#Eval("Age") %>' runat="server"></asp:Label> 
      </ItemTemplate> 
     </asp:TemplateField> 
    </Columns> 
</asp:GridView> 

Y su código detrás para que el control sería algo como esto:

public partial class SimpleGrid : CustomGridControl 
{ 
    public override object DataSource 
    { 
     get { return myGridView.DataSource; } 
     set { myGridView.DataSource = value; } 
    } 
} 

Ahora la página o de control que utiliza esto solo tiene que convertirse a la clase base, y puedes usarlo genéricamente. El siguiente es un ejemplo sencillo de cómo puede usar esto, pero creo que hace que el punto claramente:

protected void Page_Load(object sender, EventArgs e) 
{ 
    var dataSource = new List<MyCustomClass> 
         { 
          new MyCustomClass{Name = "Josh", Age = 43}, 
        new MyCustomClass{Name = "Bob", Age = 14}, 
        new MyCustomClass{Name = "Ashley", Age = 32}, 
         }; 

    DynamicallyLoadUserControlGrid("~/GridViewTemplates/SimpleGrid.ascx", dataSource); 
} 

private void DynamicallyLoadUserControlGrid(String controlLocation, List<MyCustomClass> dataSource) 
{ 
    var ctrl = (CustomGridControl)LoadControl(controlLocation); 
    ctrl.DataSource = dataSource; 
    ctrl.DataBind(); 

    GridViewPlaceHolder.Controls.Add(ctrl); 
} 

Así que, ahí lo tienen. Controles de plantilla personalizados sin el desagradable dolor de cabeza de tratar de compilarlos todos manualmente en el código. Voy a publicar el completamente manual manera de hacer esto en otra respuesta, pero una vez que lo vea, creo que estará de acuerdo en que este método es preferido.

+0

Tanque mucho, funcionó muy bien después de que entendí el punto :) –

5

Muy bien, así que aquí está la creación 100% manual de campos con plantillas ejemplo.

El primer paso para crear columnas de plantilla dinámicas es crear una clase que implemente la interfaz System.Web.UI.ITemplate. Para nuestro ejemplo simple aquí, solo voy a usar una etiqueta.

public class MyCustomTemplate : ITemplate 
{ 
    public String DataField { get; set; } 

    public MyCustomTemplate(String dataField) 
    { 
     DataField = dataField; 
    } 

    public void InstantiateIn(Control container) 
    { 
     var label = new Label(); 
     label.DataBinding += label_DataBinding; 

     container.Controls.Add(label); 
    } 

    void label_DataBinding(object sender, EventArgs e) 
    { 
     var label = (Label)sender; 
     var context = DataBinder.GetDataItem(label.NamingContainer); 
     label.Text = DataBinder.Eval(context, DataField).ToString(); 
    } 
} 

Tenga en cuenta que con el fin de apoyar DataBinding, que tendrá que manejar manualmente ese evento en cualquier testigo (s) decide añadir. Una vez que haya desarrollado su plantilla, puede usarla como su Plantilla de elemento para cualquier TemplateField que quiera usar.

Supongamos que tenemos una colección de objetos comerciales personalizados a los que queremos unir nuestra grilla.

public class MyCustomClass 
{ 
    public String Name { get; set; } 
    public Int32 Age { get; set; } 
} 

vamos a tener que construir manualmente cada columna como un TemplateField, y luego unirse a nuestra colección GridView. Con el fin de hacer que este limpio y más fácil de hacer, he encapsulado la construcción de la colección TemplateField en una clase auxiliar estática:

public static class MyCustomTemplateCollection 
{ 
    public static DataControlFieldCollection GetTemplateCollection() 
    { 
     var col = new DataControlFieldCollection(); 

     var nameField = new TemplateField 
         { 
          HeaderText = "Name", 
          ItemTemplate = new MyCustomTemplate("Name") 
         }; 

     var ageField = new TemplateField 
         { 
          HeaderText = "Age", 
          ItemTemplate = new MyCustomTemplate("Age") 
         }; 

     col.Add(nameField); 
     col.Add(ageField); 

     return col; 
    } 
} 

El uso de este en su código detrás sería algo como esto:

protected void Page_Load(object sender, EventArgs e) 
{ 
    var dataSource = new List<MyCustomClass> 
         { 
          new MyCustomClass{Name = "Josh", Age = 43}, 
        new MyCustomClass{Name = "Bob", Age = 14}, 
        new MyCustomClass{Name = "Ashley", Age = 32}, 
         }; 

    DynamicGrid(dataSource); 
} 

private void DynamicGrid(List<MyCustomClass> dataSource) 
{ 
    var col = MyCustomTemplateCollection.GetTemplateCollection(); 

    foreach (DataControlField field in col) 
    { 
     myGridView.Columns.Add(field); 
    } 

    myGridView.DataSource = dataSource; 
    myGridView.DataBind(); 
} 

Al final, esto producirá una salida que es idéntica al ejemplo de controles dinámicos del usuario, pero como puede ver, es mucho más engorroso. Este también es un ejemplo muy simplista que no incluye ningún atributo CSS o múltiples tipos de controles. Podrías hacer esto, pero sería doloroso y podrías querer dejar de programar todos juntos. Vaya con la solución de control de usuario y haga su vida más fácil.

Cuestiones relacionadas