En este
post, vamos a explicar paso a paso cómo se puede personalizar completamente una
columna de un GridView por código. En concreto, lo que realizaremos una personalización de
una columna con un CheckBox (que permita su edición), y una cabecera que
seleccione todas las filas del grid.
Para ello
debemos crear una plantilla para la columna
y una vez realizada, referenciarla desde la página del CodeBehind, indicándole
así al grid cómo debe mostrar la información.
Dado que
sería muy largo, lo he dividido en dos partes:
Parte I: Generación de la plantilla
PASO 1: Generación de la plantilla ITemplate
PASO 2: Control de eventos
Parte II: Construcción del GridView
PREVIO:
En este ejemplo, vamos a construir una columna de
CheckBox que controla un listado de test realizados por usuarios. El
nombre de cada columna hará referencia al campo equivalente en la DDBB (así, Test1 sería la columna de los datos para
el Test1). Además vamos a incluir en la cabecera una imagen que al pulsar, seleccionará todos los checks del gridview.
Parte I: Generación de la plantilla
PASO 1: Generación de la clase ITemplate
Para poder
referenciar nuestra columna desde el GridView, necesitamos proporcionarle al
sistema una forma de generar nuestra columna de CheckBox. Para ello hay que
crear una clase que implemente el interfaz
ITemplate.
En nuestro ejemplo, denominaremos a la clase GridViewCheckboxTemplate.
public
class GridViewCheckboxTemplate
: ITemplate
{
//Event handler - boton Header para “Seleccionar
Todos”
public event EventHandler ImageClick;
//atributo para almacenar el ListItemType.
ListItemType
_templateType;
//Atributo con el nombre identificador de la columna.
private string
_columnName;
//Constructor donde definimos el tipo y nombre.
public GridViewCheckboxTemplate(ListItemType type, string colname)
{
_templateType = type;
_columnName = colname;
}
}
El ListItemType es
el que nos indicará que parte del GridViewColumn estamos editando. Los valores
que puede tomar son Header, Item,
EditItem y Footer.
NOTA: En este caso, estamos generando
una columna a partir de un constructor con 2 parametros. Podríamos crear otros
constructores con más parámetros, en función de las necesidades.
Una vez
implementados los atributos y el constructor, debemos indicar al sistema cómo
ha de generar la vista de la columna en el GridView. Para ello, implementaremos
el método ITemplate.InstantiateIn:
void
ITemplate.InstantiateIn(System.Web.UI.Control container)
{
switch
(_templateType)
{
case ListItemType.Header:
//TODO – elementos de la cabecera.
break;
case ListItemType.Item:
//TODO – CheckBox en formato PRESENTACIÓN.
break;
case ListItemType.EditItem:
//TODO – CheckBox en formato EDICIÓN.
break;
case
ListItemType.Footer:
//TODO – elementos del footer.
break;
}
}
En la definición del
método anterior podemos observar que, en función del tipo de ítem que estemos
solicitando, el sistema generará unos controles u otros para el render de la columna completa. Por tanto,
ya podemos incluir los controles necesarios para nuestra personalización:
HEADER:
case
ListItemType.Header:
ImageButton imgButton = new ImageButton();
imgButton.ID = "imgHeader_"
+ _columnName;
imgButton.ImageUrl = "~/images/ico/check_all.png";
imgButton.ImageAlign =
ImageAlign.AbsMiddle;
imgButton.ToolTip = "Activar TODOS ";
imgButton.Click += new
ImageClickEventHandler(imgHeader_ClickEventHandler);
imgButton.Attributes.Add("onclick", "return
confirm('¿Seguro que desea activar todas las filas?');");
container.Controls.Add(imgButton);
//Creamos el label que indica en qué columna estamos.
Label
lbl = new Label();
lbl.Text = "
"+_columnName;
container.Controls.Add(lbl);
break;
Como se puede observar, para
cada control establecemos todas sus propiedades, entre las que cabe destacar:
· La Url relativa a la raíz
del proyecto la imagen que vamos a mostrar:
· El evento que se
disparará cuando se pulse sobre la imagen. Más adelante veremos cómo programar esta
función:
imgButton.Click += new ImageClickEventHandler(imgHeader_ClickEventHandler);
· Una confirmación de
activación para todos los elementos:
imgButton.Attributes.Add("onclick",
"return confirm('¿Seguro que desea activar todas
las filas?');");
ITEM y EDITITEM:
Como sólo vamos a
mostrar un checkBox, simplemente debemos añadir dicho control a la columna:
case
ListItemType.Item:
//Creamos el
checkBox.
CheckBox chk = new
CheckBox();
chk.EnableViewState = true;
chk.Enabled = false; //en vista, NO PERMITIMOS la modificación del valor.
chk.ID
= "chkItem_" + _columnName;
chk.DataBinding += new
EventHandler(CB1_DataBinding); //enlace a datos.
container.Controls.Add(chk);
break;
case
ListItemType.EditItem:
// Creamos el checkbox
para edición
CheckBox chkEdit = new
CheckBox();
chkEdit.EnableViewState = true;
chkEdit.Enabled = true; //en edición, PERMITIMOS la modificación del valor
chkEdit.ID
= "chkEditItem_" + _columnName;
chkEdit.DataBinding += new EventHandler(CB1_DataBinding); //enlace a datos.
container.Controls.Add(chkEdit);
break;
A
destacar el DataBinding que se
encargará de mostrar la información al generar el GridView (ver paso 2 ‘Control de Eventos’), y la opción Enabled que es la que permite la modificación del estado del checkbox.
FOOTER:
En este ejemplo, no
añadimos ningún elemento al footer, pero se podría personalizar con cualquier control
que necesitaramos. Como ejemplos; un botón para añadir un nuevo ítem, ó un
Label con información del total de registros, o ubicar aquí el selector multiple, etc.
NOTA: Recordar que si incluimos aquí cualquier control, en vista de diseño deberemos marcar el atributo ShowFooter a true.
NOTA: Recordar que si incluimos aquí cualquier control, en vista de diseño deberemos marcar el atributo ShowFooter a true.
PASO 2: Control de eventos
Una vez generado el método
para construir la columna debemos controlar los eventos de datos y, en este
ejemplo, del botón header para ‘Seleccionar
todos’.
Control del click
sobre la imagen
void
imgHeader_ClickEventHandler(object sender,
ImageClickEventArgs e)
{
if
(ImageClick != null) { ImageClick(sender, EventArgs.Empty); }
}
Aquí simplemente
verificamos que existe un EventHandler asociado a la imagen y en caso afirmativo, llamamos al
delegado. Éste será el encargado de modificar los datos y actualizar el grid.
Control de los datos
a mostrar
void CB1_DataBinding(object sender, EventArgs
e)
{
CheckBox chk = (CheckBox)sender; //Obtenemos
el control
GridViewRow container =
(GridViewRow)chk.NamingContainer; //contenedor con
datos
object
dataValue = DataBinder.Eval(container.DataItem, _columnName); //valor obtenido
chk.Checked = (dataValue.ToString() == "1"); //actualización
del check
}
Aquí obtendremos el
valor a mostrar en el CheckBox. Dado que en este ejemplo, en la DDBB tenemos una columna ‘Bit’,
deberemos marcar la selección en función de si el valor es ‘0’ ó ‘1’.
Llegados a este punto, ya tenemos configurada nuestra plantilla completa para la columna del gridView. Recordad que en este ejemplo estamos trabajando con un CheckBox, pero se podría personalizar para cualquier tipo de control e información que os hiciese falta.
En el próximo post
indicaré cómo hacer uso de esta clase, para generar nuestro grid personalizado.
Un saludo a todos!
como muestro una imagen en gridview pero esta incluida en un campo de mi base de datos, no es dirección de la foto si no esta en un campo image
ResponderEliminarNo creo que necesites implementar todo un grid view personalizado. Simplemente podrías generar un ascx, o una página que mostrase dicha imagen a partir de un parametro dado.
EliminarAquí tienes una buena referencia, que espero te sirva: http://www.aspsnippets.com/articles/display-images-from-sql-server-database-in-asp.net-gridview-control.aspx