Gerardo Contijoch

Experiencias del día a día trabajando con .NET – ASP.NET, C#, ASP.NET MVC y demas…

Generación personalizada de Ids en ASP.NET 4.0

Posted by Gerardo Contijoch en junio 12, 2009

En mi último post les comentaba sobre un gran problema que hay en ASP.NET (por lo menos hasta que salga la 4.0) con respecto a la generación automática de los ids de controles web. Resumidamente, el problema esta en que ASP.NET puede cambiar el id original que le dimos a nuestros controles (por ejemplo, txtNombre por “ctl00_ContentPlaceHolder1_txtNombre”), lo cual suele provocar que nuestros scripts en javascript deje de funcionar. Casualmente, unas horas después de publicado el post, me encuentro con éste artículo en donde se explica como en ASP.NET 4.0 esto deja de ser un problema ya que se permite la personalización del proceso de generación de ids.

Cabe aclarar que el comportamiento que voy a describir a continuación esta basado en ASP.NET 4.0 CTP y no en la versión definitiva (la cual no salió aún), pero imagino que este es uno de los puntos en donde no va a cambiar el funcionamiento. Otro punto a aclarar es que el id se ve modificado sólo del lado del cliente, es decir, el código del lado del servidor no se ve modificado en nada.

El atributo ClientIDMode

La personalización del Id ahora se puede realizar mediante un nuevo atributo de los controles web llamado ClientIDMode. Dependiendo de su valor, el id generado para el control que lo aplique puede ser fijo (siempre el mismo), dinámico (basado en datos asociados al control) o automático (es decir, igual que en las versiones anteriores de ASP.NET).

Sus valores posibles son:

  • Legacy
  • Static
  • Predictable
  • Inherit

Veamos uno por uno.

Legacy

Este valor indica que el comportamiento de ASP.NET al generar el id va a ser igual al de las versiones anteriores, es decir, el id va a tener el siguiente formato: [IdControlContenedor]_[IdControlHijo].

Static

Éste sea posiblemente el valor más utilizado ya que indica que el id generado sea el que definimos nosotros (es decir, que quede estático o fijo) y no se vea modificado por nada. Hay que tener en mente que esto puede traer conflictos de ids si hay un contenedor con un control con el mismo id dentro de este. Por ejemplo:

   1: <body>
   2:     <form id="form1" runat="server">
   3:     <div>
   4:         <asp:TextBox ID="txtNombre" runat="server" ClientIDMode="Static"></asp:TextBox>
   5:         <uc1:MiControlWeb ID="MiControlWeb1" runat="server" />
   6:     </div>
   7:     </form>
   8: </body>

Donde MiControlWeb esta definido así:

   1: <%@ Control Language="C#" AutoEventWireup="true" CodeFile="MiControlWeb.ascx.cs" Inherits="WebUserControl" %>
   2: <asp:TextBox ID="txtNombre" runat="server" ClientIDMode="Static"></asp:TextBox>

Esto quedaría renderizado así:

   1: <div>
   2:   <input name="txtNombre" type="text" id="txtNombre" />
   3:   <input name="MiControlWeb$txtNombre" type="text" id="txtNombre" />
   4: </div>

Este atributo no debería usarse nunca dentro de un control como Repeater, ya que los ids de los controles contenidos en el serían todos iguales.

Inherit

Este es el modo por defecto, y simplemente indica que el valor de ClientIDMode se hereda del contenedor donde se encuentre el control (como pueden ser un WebControl, un ContentPlaceHolder – en MasterPages- o una página).

Predictable

Este modo de generación produce resultados similares al modo Legacy pero, como lo indica su nombre, los valores son predecibles. Es principalmente útil en los controles enlazados a datos. El id en este caso se genera mediante el uso del dato asociado o enlazado al control. Veamos como funciona.

Dado este control:

   1: <asp:GridView ID="gvPersonas" runat="server" AutoGenerateColumns="false" ClientIDMode="Predictable">
   2: <Columns>
   3:     <asp:TemplateField HeaderText="Id">
   4:          <ItemTemplate>
   5:               <asp:Label ID="lblPersonaId" runat="server" Text='<%# Eval("Id") %>' />
   6:          </ItemTemplate>
   7:     </asp:TemplateField>
   8:     <asp:TemplateField HeaderText="Nombre">
   9:          <ItemTemplate>
  10:               <asp:Label ID="lblNombre" runat="server" Text='<%# Eval("Nombre") %>' />
  11:          </ItemTemplate>
  12:     </asp:TemplateField>
  13:     <asp:TemplateField HeaderText="Apellido">
  14:          <ItemTemplate>
  15:               <asp:Label ID="lblApellido" runat="server" Text='<%# Eval("Apellido") %>' />
  16:          </ItemTemplate>
  17:     </asp:TemplateField>
  18: </Columns>
  19: </asp:GridView>

El Html renderizado se vería así:

   1: <table id="gvPersonas" style="border-collapse: collapse" cellspacing="0" rules="all" border="1">
   2:   <tbody>
   3:     <tr>
   4:        <th scope="col">Id</th>
   5:        <th scope="col">Nombre</th>
   6:        <th scope="col">Apellido</th>
   7:     </tr>
   8:     <tr>
   9:        <td><span id="gvPersonas_lblPersonaId_0">1</span></td>
  10:        <td><span id="gvPersonas_lblNombre_0">Juan (primer persona)</span></td>
  11:        <td><span id="gvPersonas_lblApellido_0">Lopez</span></td>
  12:     </tr>
  13:     ...
  14:     <tr>
  15:        <td><span id="gvPersonas_lblPersonaId_35">36</span></td>
  16:        <td><span id="gvPersonas_lblNombre_35">Gerardo (36ta persona)</span></td>
  17:        <td><span id="gvPersonas_lblApellido_35">Contijoch</span></td>
  18:     </tr>
  19:   </tbody>
  20: </table>

Noten el sufijo numérico al final de los Ids. Este sufijo puede ser personalizado en los controles enlazados a datos para que sea otro valor y no un simple índice. Esto se logra mediante la aplicación del atributo RowClientIDSuffix. El valor de este atributo debe ser nombre de la propiedad o columna (dependiendo del origen de datos) cuyo valor deseamos incluir en el Id. Veamos un ejemplo para aclarar esto. Dado este código:

   1: <asp:GridView ID="gvPersonas" runat="server" AutoGenerateColumns="false" ClientIDMode="Predictable" RowClientIDSuffix="Apellido">
   2: <Columns>
   3:     <asp:TemplateField HeaderText="Id">
   4:          <ItemTemplate>
   5:               <asp:Label ID="lblPersonaId" runat="server" Text='<%# Eval("Id") %>' />
   6:          </ItemTemplate>
   7:     </asp:TemplateField>
   8:     <asp:TemplateField HeaderText="Nombre">
   9:          <ItemTemplate>
  10:               <asp:Label ID="lblNombre" runat="server" Text='<%# Eval("Nombre") %>' />
  11:          </ItemTemplate>
  12:     </asp:TemplateField>
  13:     <asp:TemplateField HeaderText="Apellido">
  14:          <ItemTemplate>
  15:               <asp:Label ID="lblApellido" runat="server" Text='<%# Eval("Apellido") %>' />
  16:          </ItemTemplate>
  17:     </asp:TemplateField>
  18: </Columns>
  19: </asp:GridView>

Se genera lo siguiente:

   1: <table id="gvPersonas" style="border-collapse: collapse" cellspacing="0" rules="all" border="1">
   2:   <tbody>
   3:     <tr>
   4:        <th scope="col">Id</th>
   5:        <th scope="col">Nombre</th>
   6:        <th scope="col">Apellido</th>
   7:     </tr>
   8:     <tr>
   9:        <td><span id="gvPersonas_lblPersonaId_Lopez">1</span></td>
  10:        <td><span id="gvPersonas_lblNombre_Lopez">Juan (primer persona)</span></td>
  11:        <td><span id="gvPersonas_lblApellido_Lopez">Lopez</span></td>
  12:     </tr>
  13:     ...
  14:     <tr>
  15:        <td><span id="gvPersonas_lblPersonaId_Contijoch">36</span></td>
  16:        <td><span id="gvPersonas_lblNombre_Contijoch">Gerardo (36ta persona)</span></td>
  17:        <td><span id="gvPersonas_lblApellido_Contijoch">Contijoch</span></td>
  18:     </tr>
  19:   </tbody>
  20: </table>

Si prestan atención, verán que el sufijo ahora es el valor del campo Apellido en nuestro origen de datos. Una característica interesante del atributo RowClientIDSuffix es que acepta más de un único valor, por lo que es posible definir nuestro control así:

   1: <asp:GridView ID="gvPersonas" ... ClientIDMode="Predictable" RowClientIDSuffix="Id, Apellido">

Generando un HTML como este:

   1: ...
   2: <tr>
   3:    <td><span id="gvPersonas_lblPersonaId_1_Lopez">1</span></td>
   4:    <td><span id="gvPersonas_lblNombre_1_Lopez">Juan (primer persona)</span></td>
   5:    <td><span id="gvPersonas_lblApellido_1_Lopez">Lopez</span></td>
   6: </tr>
   7: ...

Se puede ver que el sufijo ahora consiste en el campo Id y el campo Apellido.

Referencias:

¡Nos vemos en el próximo post!

Publicado originalmente en https://gerardocontijoch.wordpress.com.

Una respuesta to “Generación personalizada de Ids en ASP.NET 4.0”

  1. Carol said

    Hola, tu sabes la forma en que puedo colocar el ID en 2 palabras más espacio ej (custom edad) de un textbox en asp.net visual studio 2010. Necesito colocar el id de esa forma.

Deja un comentario