Esta entrada salió como resultado de una pregunta que hicieron en el Foro de la Comunidad .NET. La pregunta, esencialmente, es: ¿Cómo accedo a un control que tengo en una columna templeteada dentro de un GridView de ASP.NET?
Me pareció buena la pregunta, así que hice un pequeño ejemplo para ilustrarlo. Una columna templeteada (TemplateField) es distinta a una normal (BoundField) en que tienes más control sobre los controles que aparecen en la columna. En otras palabras, tú especificas qué quieres que se muestre cuando el renglón está en modo "normal" (ItemTemplate) o cuando está en modo "edición" (EditItemTemplate). Puedes tener múltiples controles dentro de la columna, en lugar de solo uno que represente el dato.
La siguiente página contiene un GridView con tres columnas que vienen de un SqlDataSource. Los datos provienen de la clásica base de datos Northwind. En este caso estoy recuperando datos de la tabla de productos:
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb"
Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Accediendo a Elementos en un GridView</title>
<style type="text/css">
#miGrid
{
width: 450px;
float: left;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:Button runat="server" ID="leerElementosButton" Text="Leer elementos" />
<div id="miGrid">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="SqlDataSource1"
EmptyDataText="No hay registros que mostrar.">
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ID Producto"
InsertVisible="False" ReadOnly="True" />
<asp:BoundField DataField="ProductName" HeaderText="Nombre Producto" />
<asp:TemplateField HeaderText="Descontinuado">
<EditItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server"
Checked='<%# Bind("Discontinued") %>' />
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server"
Checked='<%# Bind("Discontinued") %>' Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>"
SelectCommand="SELECT [ProductID], [ProductName], [Discontinued] FROM [Products]">
</asp:SqlDataSource>
</div>
<div id="resultados">
<asp:Label runat="server" ID="resultadosLabel" />
</div>
</form>
</body>
</html>
Para acceder, por ejemplo, al CheckBox que está dentro de la columna templeteada, primero necesitas una referencia al renglón, ya que el ID del control se repetirá n veces (una por cada renglón del Grid).
Esto se puede hacer de varias formas, por ejemplo, si tienes un manejador para un evento clic en alguno de los controles dentro del renglón pues en ese caso el sender viene siendo el renglón en sí, entonces únicamente te falta encontrar el CheckBox de ese renglón para leer sus propiedades. Otra forma de hacerlo, como en el siguiente ejemplo, es leer todos los renglones y por cada uno encontrar el CheckBox que le corresponde al renglón:
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub leerElementosButton_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles leerElementosButton.Click
Dim grid As GridView = Me.GridView1
Dim checkBox As CheckBox
Dim resultado As New StringBuilder
For Each renglon As GridViewRow In grid.Rows
checkBox = CType(renglon.FindControl("CheckBox1"), CheckBox)
If checkBox.Checked Then 'Hacer algo con esta información
resultado.Append(String.Format( _
"El renglón {0} está descontinuado <br />", renglon.DataItemIndex))
End If
Next
resultadosLabel.Text = resultado.ToString()
End Sub
End Class
En resúmen, la idea clave aquí es que el GridView tiene una colección de renglones (de tipo GridViewRow) y cada uno de estos renglones tiene su correspondiente colección de controles que están dentro de ese renglón. El GridViewRow también te da acceso al DataItem que contiene los datos asociados al renglón, en caso de que lo requirieras.
El resultado de correr el código anterior (dando clic al botón) es el siguiente:
Espero les ayude.
Enjoy 