Utilizar la Base de Datos como repositorio de imágenes (I)
En cierto proyecto necesitaba mostrar una serie de imágenes que el usuario debía insertar desde su equipo local. En un principio pensé enviar al servidor las imágenes, guardar la ruta relativa en Base de Datos y, cuando fuese necesario acceder a las imágenes, utilizar dicha ruta para acceder a la imagen. Pero no era tan sencillo. Por desgracia, no teníamos permiso de escritura en el disco duro, por lo que tenía que juguetear con las imágenes sin que éstas existieran físicamente. ¿Cómo? Almacenando y recuperando las imágenes de base de datos.
Guardando una imagen en SQL Server
Para empezar, veremos cómo almacenar en base de datos una imagen. Crearemos, desde el SQL Server Management Studio, una nueva tabla que tendrá tres campos:
- Un Id único entero y autoincrementable (IdImagen)
- Un nombre para la imagen nvarchar(50) (NombreImagen)
- Una secuencia de bytes, variable de tipo image (Fichero).
Creada la tabla, crearemos una página que, a partir de la ruta de la imagen, la inserte en base de datos. Podemos utilizar un Input File o un control similar para indicarle la ruta, pero aquí indicaremos únicamente el código necesario para subir la imagen dada su ruta física. Lo que haremos a continuación será lo siguiente:
- Crear una conexión a Base de Datos a partir de una cadena de conexión
string ConnectionString = @"Data Source=DANIGARCIA\SQLSERVER2005;Initial Catalog=TestDB;Persist Security Info=True;User ID=dani;Password=c0ntr4s3n14";
- Crear una cadena de texto con la sentencia INSERT.
string CommandString = "INSERT INTO Imagen(NombreImagen, Fichero) VALUES (@NombreImagen, @Fichero)";
- A continuación necesitaremos convertir nuestra imagen en un objeto que podamos manejar, por ejemplo un array de bytes. Para ello, a partir de la ruta física de la imagen crearemos un objeto de tipo System.Drawing.Bitmap que guardaremos en un MemoryStream que, a su vez, convertiremos en un array de bytes (byte[]).
byte[] bImagen = null; System.IO.MemoryStream ms = new System.IO.MemoryStream(); System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(@"C:\TEMP\inicio.jpg"); if (bmp != null) { bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); bImagen = ms.ToArray(); ms.Close(); }
- Instanciar un objeto de tipo SqlCommand a partir de la conexión y de la sentencia INSERT.
SqlConnection conexion = new SqlConnection(ConnectionString); SqlCommand command = new SqlCommand(CommandString, conexion);
- Añadiremos ahora los SqlParameters necesarios al objeto SqlCommand con los datos a insertar en la base de datos. Estos serán, en nuestro caso, el nombre de la imagen y el array de bytes con la imagen.
SqlParameter nombre = new SqlParameter("@NombreImagen", "inicio.jpg"); SqlParameter imagen = new SqlParameter("@Fichero", bImagen);
- Por último, abrimos la conexión, ejecutamos la sentencia mediante ExecuteNonQuery() y cerramos la conexión. Hecho esto, tendremos nuestra imagen almacenada en base de datos.
conexion.Open(); command.Parameters.Add(nombre); command.Parameters.Add(imagen); command.ExecuteNonQuery(); conexion.Close();
Hecho esto insertaremos una imagen en una tabla de la base de datos.
Más adelante aprenderemos cómo recuperarla y referenciarla directamente a través de una URL con extensión aspx, es decir, invocar una ruta de tipo getImage.aspx?Id=xxx.
Variables de servidor en ASP.NET
Nuestro servidor ASP.NET aloja una gran cantidad de información útil que, en determinado momento, puede salvarnos de situaciones complejas. Este conjunto de variables puede consultarse mediante el objeto Request.ServerVariables[<NombreVariable>]. Así, si realizamos la siguiente consulta:
string navegador = Request.ServerVariable["HTTP_USER_AGENT"];
La variable navegador alojará, como intuitivamente podremos imaginar, el navegador que está utilizando el cliente que se conecta a nuestro servidor, dato utilizado, por ejemplo, para estadísticas. En nuestro caso, el dato devuelto será el siguiente:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Hay cantidad de variables de servidor cuya consulta puede hacernos la vida más fácil. Como ejemplo, indicaremos algunas de ellas:
| VARIABLE | SIGNIFICADO | EJEMPLO |
|---|---|---|
| SERVER_PROTOCOL | Protocolo de conexión | HTTP/1.1 |
| REMOTE_ADDR | Dirección IP Remota | 80.24.53.11 |
| LOCAL_ADDR | Direccion IP Local | 127.0.0.1 |
| PATH_INFO | Ruta de la aplicación | /MiAplicacion/Pagina.aspx |
| URL | URL de la página | /MiAplicacion/Pagina.aspx |
| AUTH_TYPE | Tipo de autenticación | Forms |
| SERVER_PORT | Puerto HTTP | 80 |
| HTTP_USER_AGENT | Navegador del usuario | Mozilla/4.0 (compatible; MSIE 8.0;… |
| HTTP_HOST | Nombre del host | MyMachine |
| SERVER_NAME | Nombre del servidor | MyMachine |
| SERVER_SOFTWARE | Servidor web | Microsoft-IIS/6.0 |
| APPL_PHYSICAL_PATH | Ruta física de la aplicación | C:\\Inetpub\\wwwroot\\MiAplicacion\\ |
| HTTPS | ¿Usa SSL? | off |
| AUTH_USER | Usuario autenticado | administrador |
| REMOTE_USER | Usuario remoto | administrador |
| HTTP_CONNECTION | Tipo de conexión HTTP | Keep alive |
| HTTP_ACCEPT_LANGUAGE | Idioma | es |
Existen más variables de servidor, y basta con recorrer con un bucle su contenido para echarle un vistazo a todas:
Hashtable hs = new Hashtable();
foreach (string s in Request.ServerVariables.AllKeys)
{
hs.Add(s, Request.ServerVariables[s]);
}
Enviar un e-mail desde .NET utilizando una cuenta SMTP de GMail
En mi proyecto de fin de carrera implementé un sistema automatizado de reservas que avisaba por e-mail del estado de las mismas. Para mi desgracia, olvidé mencionarlo durante la defensa, por lo que a nivel institucional fue una pérdida de tiempo, pero no así a nivel didáctico (que es, a fin de cuentas, lo importante).
Para implementarlo, utilicé los espacios de nombres System.Net y System.Net.Mail y una cuenta de Gmail a la que previamente le había activado el acceso POP/SMTP. Mandar un mail desde .NET es relativamente sencillo.
Si pensamos en la composición de un mail en términos de objetos, veremos que en realidad, enviar un mail es muy, pero que muy sencillo. Imaginemos que tenemos una cuenta en Gmail, por ejemplo ‘estoesunapruebademail25@gmail.com‘, cuya contraseña es ‘inteligible43‘. Queremos mandar un correo. ¿Qué información necesitamos?
- Un mensaje, que implementará la clase MailMessage.
- Un cliente de correo (SmtpClient) que se encargue de la autenticación y envío del mensaje.
A su vez, el mensaje necesitará:
- Uno o varios destinatarios.
- Un remitente.
- Un asunto (subject).
- El texto del mensaje.
Mientras que el cliente del correo necesitará saber:
- Servidor SMTP al que conectarse y puerto.
- Nombre de usuario y contraseña.
Almacenamiento y recuperación de parámetros en Sesión y ViewState
Muchas veces necesitamos utilizar parámetros entre distintos métodos de un mismo formulario web, o incluso entre formularios distintos. Una forma dinámica de realizar este intercambio de datos es la utilización del ViewState y del espacio de sesión.
Antes de embarcarnos a almacenar datos y datos en estos dos espacios de memoria, hay que dejar claras dos cosas:
- El ViewState se intercambia continuamente entre cliente y servidor, por lo que es aconsejable no sobrecargarlo. Al aumentar el ViewState, aumentará el tamaño de la página, y por consiguiente, el tráfico de datos y la velocidad de carga de la misma.
- La sesión se almacena en servidor, por lo que si nuestro sitio web posee una carga de datos moderada - alta, el rendimiento del mismo se verá penalizado. Nuevamente, es aconsejable utilizar con cautela este espacio de memoria.
Teniendo claros estos dos conceptos, utilizaremos el ViewState para almacenar datos locales (de una misma página) y la sesión para pasar parámetros entre distintas páginas sin hacer uso de la QueryString. Para los profanos en la materia, explicaremos que la QueryString es la colección de parámetros que pueden, opcionalmente, acompañar a la dirección de la página. Éstos parámetros ofrecen información directamente recopilable por nuestro formulario web, pero cuenta con la desventaja de que es visible para el usuario.
Servicios Web (II): Consumiendo un servicio web
Veíamos anteriormente cómo crear un servicio web simple. A continuación veremos cómo consumirlo.
Si crear un WebService no tiene demasiada dificultad, consumirlo es, si cabe, mucho más sencillo. Crearemos una aplicación web normal y corriente, y sobre ésta, haremos click derecho y seleccionaremos la opción [Agregar Referencia Web...]

Hecho esto, se desplegará un menú que nos permitirá la detección de servicios web. Si introducimos la dirección en la que el servicio está publicado y pulsamos en “Ir” se nos mostrará los métodos que el servicio expone. En la caja de texto derecha añadiremos el nombre que tendrá nuestra referencia (por ejemplo, ServicioSimple) y pulsaremos sobre [Agregar referencia].

Hecho esto, se agregará a nuestro proyecto una referencia a nuestro servicio web, que se mostrará en nuestro proyecto de la siguiente manera:

Finalmente, añadiremos controles a nuestra página para comprobar que nuestra aplicación se comunica perfectamente con el servicio web. Para ello crearemos un GridView, dos Label, una caja de Texto y tres botones.
En el primer botón codificaremos la funcionalidad para cargar el GridView con la primera tabla del DataSet devuelto por el método GetData() de nuestro servicio web. Para ello crearemos una referencia a nuestro servicio, crearemos una referencia a un DataSet e invocaremos el método GetData() del WebService. Finalmente rellenaremos el Grid con el resultado obtenido.
protected void ButtonGrid_Click(object sender, EventArgs e)
{
// Referenciamos el servicio
ServicioSimple.Service referenciaServicio = new ServicioSimple.Service();
// Creamos una referencia a un DataSet
DataSet ds;
// Invocamos el WebMethod GetData()
ds = referenciaServicio.GetData();
// Rellenamos el DataGrid
GridViewDatos.DataSource = ds.Tables[0];
GridViewDatos.DataBind();
}
En el segundo botón haremos que nuestro label muestre el resultado de la invocación al método GetDate(), que recordemos que devolvía la fecha actual.
protected void ButtonFecha_Click(object sender, EventArgs e)
{
// Referenciamos el servicio
ServicioSimple.Service referenciaServicio = new ServicioSimple.Service();
LabelFecha.Text = referenciaServicio.GetDate().ToString();
}
Por último, el tercer botón mostrará el resultado de invocar al método GetDateDiff(int). Para ello le pasaremos al WebService un parámetro que indicará el número de horas que tiene que añadir. Para ello utilizaremos la caja de texto.
protected void ButtonFechaDiff_Click(object sender, EventArgs e)
{
// Referenciamos el servicio
ServicioSimple.Service referenciaServicio = new ServicioSimple.Service();
if (!string.IsNullOrEmpty(TextBoxDiferencia.Text))
{
LabelFechaDiferencia.Text = referenciaServicio.GetDateDiff(Convert.ToInt32(TextBoxDiferencia.Text)).ToString();
}
}
Hecho. Ya hemos creado un servicio web y hemos aprendido a consumirlo.

Servicios Web (I): Creando un servicio web simple
Un servicio web no es más que un conjunto de protocolos y estándares cuyo objetivo es el intercambio de información entre distintas aplicaciones. Los servicios web tienen la peculiaridad de ser independientes de plataforma, es decir, cumplen estándares propios y no dependen ni del hardware sobre el que se ejecuta ni del sistema operativo o servidor web que lo aloja.
Un servicio web intercambia información. Al invocar un servicio web estamos realizando una petición a otra máquina, a la que (opcionalmente) le enviamos información, la procesa y nos devuelve una respuesta, generalmente atómica y serializable, es decir: lo común es que un servicio web nos devuelva un dato o estructura de datos con la información que necesitemos (atómica) en forma de cadena de texto (serializable). Esto es así por el lenguaje común que “hablan” los servicios web: XML.
Si quisiéramos crear un servicio web, en una solución en blanco pulsaríamos sobre Agregar > Nuevo sitio Web…

Hecho esto, seleccionaremos la plantilla “Servicio Web ASP.NET”, y alojaremos el servicio web en nuestro IIS indicándole la ruta que deseemos.

A continuación, crearemos los métodos que queramos exponer, añadiendo el atributo [WebService] a la clase y el atributo [WebMethod] a los métodos que deban ser expuestos.
Crearemos tres métodos: uno que devuelva la hora actual, otro que devuelva nuestra localización geográfica y otro que añada las horas pasadas como parámetro a la hora actual.
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "http://localhost/Services/Date")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
public Service () {
//Eliminar la marca de comentario de la línea siguiente si utiliza los componentes diseñados
//InitializeComponent();
}
[WebMethod]
public DateTime GetDate() {
return DateTime.Now;
}
[WebMethod]
public string GetLocation()
{
return "UTC/GMT +2, Madrid, Spain.";
}
[WebMethod]
public DateTime GetDateDiff(int horasDiferencia)
{
return DateTime.Now.AddHours(horasDiferencia);
}
}
Hecho esto, iremos a la dirección de nuestro servicio web, lo cual nos mostrará lo siguiente:

Para probar el servicio web, haremos click sobre cualquiera de los métodos expuestos. Si el webservice no requiere ningún parámetro, se nos mostrará directamente el resultado de la invocación:
![]()
En caso contrario, se nos pedirá que introduzcamos el parámetro requerido, lo cual nos llevará a la obtención del dato.

Si analizamos el contenido de la respuesta, comprobaremos que, efectivamente, se trata de un fichero XML.
<?xml version="1.0" encoding="utf-8"?>
<dateTime xmlns="http://localhost/Services/Date">2009-06-09T17:27:00.0874935+02:00</dateTime>
Posteriormente comprobaremos cómo realizar una invocación a un servicio web desde nuestra aplicación.
Abstracción de Datos (V): Aplicando el patrón Abstract Factory con C# y ADO.NET
Por norma general, un proyecto estará “atado” a una fuente de datos en particular (SQL Server, MySQL, Oracle…). Sin embargo, hay veces que esto no será así: la fuente de datos podría cambiar en cualquier momento, por lo que deberíamos ser capaces de, en la medida de lo posible, abstraer nuestra aplicación de nuestra base de datos.
Previamente comentábamos la flexibilidad otorgada por el patrón de diseño Abstract Factory. Hoy veremos una aplicación práctica, orientada precisamente a obtener práctica independencia de la fuente de datos mediante la utilización de clases comunes a todas las fuentes de datos.
Por norma general utilizamos clases específicas para lograr interactuar con una fuente de datos en concreto (por ejemplo, usaremos un objeto de la clase SqlConnection cuando trabajemos con SQL Server). Éstas clases específicas están optimizadas para trabajar con unos esquemas determinados, aportando un importante incremento del rendimiento de la aplicación. Pero como todo en esta vida, no es gratis. ¿Cuál es el precio? La portabilidad.
Añadiendo un TemplateField a un GridView de forma dinámica
La mayor parte de los sitios web que se sirven de listados lo hacen utilizando un esquema como el que sigue:

Como vemos, lo normal suele ser utilizar campos enlazados a la consulta (BoundFields), así como campos-plantilla (TemplateFields) con los que se suele interactuar con el listado (ver detalles, edición, etc.).
Si sabemos de antemano qué datos vamos a obtener, es sencillo “maquetar” nuestro GridView de forma sencilla. El problema radica en el momento en el que el número de columnas que nuestro GridView mostrará sea variable. En este caso, el atributo AutoGenerateColumns deberá ser puesto a True, con lo que perderemos el control del orden de los TemplateFields.
Veamos el siguiente caso: queremos un campo plantilla que muestre un LinkButton que nos permita editar el registro, y otro que nos permita visualizar los detalles del mismo. Queremos uno de estos campos en la primera columna (el de edición) y otro en la última (visualización). Si utilizamos TemplateFields con el atributo AutoGenerateColumns=”True”, lo que lograremos será que ambos botones se sitúen juntos en las dos primeras columnas de nuestro GridView. ¿Cómo hacer que uno de ellos se coloque al final? Añadiéndolo de forma dinámica.
Para comenzar, añadiremos un GridView con un TemplateField conteniendo un LinkButton, colocando el atributo AutogenerateColumns=”True”.

El templatefield contendría un LinkButton:

El resultado sería este:

Seguidamente, acudiremos a nuestro código, listos para editar el evento RowDataBound. En él haremos lo siguiente:
- Declararemos una celda y un LinkButton.
- Daremos formato al LinkButton (nombre, clase, etc.)
- Asignaremos al LinkButton un CommandArgument igual al Identificador (DataKey) de esa fila del GridView
- Añadiremos el LinkButton a la celda, y la celda a la fila
Para ello utilizaremos el siguiente código:
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound Try ' Si se trata de una fila de datos... If e.Row.RowType = DataControlRowType.DataRow Then Dim celda As New TableCell() Dim boton As New LinkButton() boton.Text = "Detalles" If e.Row.Cells.Count > 1 Then boton.CommandArgument = GridView1.DataKeys(e.Row.RowIndex).Value.ToString() End If ' Añadimos el LinkButton a la celda, y la celda a la fila celda.Controls.Add(boton) e.Row.Controls.Add(celda) End If Catch ex As Exception Throw ex End Try End Sub
Con esto lograremos el buscado esquema [Botón] [CAMPOS] [Botón].
Control Repeater
El control Repeater permite, como su propio nombre indica, repetir una plantilla compuesta por diversos controles un número de veces determinado, de acuerdo a una estructura de datos que pueda proveer los datos necesarios para poder rellenar esos controles. A continuación veremos un ejemplo en ASP.NET y VB.NET
Creación del control
Lo primero que debemos hacer es acceder al cuadro de herramientas y seleccionar el Repeater dentro de los controles de datos.

Control Repeater
Una vez hayamos creado el control en nuestro aspx, deberemos introducir dentro del mismo aquellos controles que queramos repetir. Nuestro Repeater tendrá, en principio, el siguiente aspecto:
<asp :Repeater ID="Repeater1" runat="server"> </asp>
En el interior del mismo podremos introducir lo que queramos: controles HTML, tablas, controles ASPX… teniendo en cuenta que todo lo que introduzcamos se repetirá un número de veces igual al número de elementos del DataSource que le asignemos al Repeater.
Es aconsejable crear la sección a repetir antes de añadirla al Repeater. Si por ejemplo queremos insertar una tabla con un GridView y un Label, cuyo código sería el siguiente:
<table cellpadding="2" cellspacing="1" bgcolor="#f6f7f9">
<tr>
<td>
<asp :GridView ID="DatosGridView" runat="server" AutoGenerateColumns="False"
BackColor="White" BorderColor="#F6F7F9" BorderStyle="Solid"
BorderWidth="1px" CellPadding="1"
DataKeyNames="Id">
<columns>
<asp :BoundField DataField="Id" HeaderText="Id" SortExpression="Id" />
<asp :BoundField DataField="Descripcion" HeaderText=" Descripcion " SortExpression=" Descripcion" />
</columns>
</asp>
<asp :Label ID="NoResultadosLabel" runat="server" Text="Label"></asp>
</td>
</tr>
</table>
Lo que obtendríamos en nuestra página sería lo siguiente:

Ejemplo de Repeater
Una vez creado el componente a repetir, cortamos su código asociado y lo introducimos dentro del Repeater, del siguiente modo:
<asp :Repeater ID="Repeater1" runat="server">
<itemtemplate>
<table cellpadding="2" cellspacing="1" bgcolor="#f6f7f9">
<tr>
<td>
<asp :GridView ID="DatosGridView" runat="server" AutoGenerateColumns="False"
BackColor="White" BorderColor="#F6F7F9" BorderStyle="Solid"
BorderWidth="1px" CellPadding="1"
DataKeyNames="Id">
<columns>
<asp :BoundField DataField="Id" HeaderText="Id" SortExpression="Id" />
<asp :BoundField DataField="Descripcion" HeaderText="Descripcion" SortExpression=" Descripcion" />
</columns>
</asp>
<asp :Label ID="EtiquetaLabel" runat="server" Text="Label"></asp>
</td>
</tr>
</table>
</itemtemplate>
</asp>
Ya tenemos una tabla con un GridView y un Label dentro del Repeater. Ahora sólo tendremos que asociarle datos para que funcione.
Enlazado de datos
El Repeater tiene un evento llamado ItemDataBound, el cual se lanza al llamar al método DataBind() del Repeater, del siguiente modo:
Dim lista As New ArrayList lista.Add(1) lista.Add(2) lista.Add(3) lista.Add(4) Repeater1.DataSource = lista Repeater1.DataBind()
La llamada al DataBind() lanzará un evento ItemDataBound por cada uno de los elementos de su DataSource. El DataSource puede ser un ArrayList, un DataTable, un DataSet, etc. En nuestro caso, el evento se lanzará cuatro veces, uno por cada valor del ArrayList.
Además, el contenido del elemento del DataSource será accesible desde el evento ItemDataBound a través de la propiedad e.Item.
Protected Sub RepeaterRecibo_ItemDataBound(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) _
Handles RepeaterRecibo.ItemDataBound
Dentro de este evento será donde realizaremos la asignación de los datos del interior del Repeater, es decir, la asignación de la propiedad Text del Label y el DataBind del GridView. Todo ello dependerá (si así lo deseamos, y es donde radica la potencia de este control) del elemento que en ese momento estemos manejando.
Si quisiéramos hacer dicho enlace, utilizaríamos el método FindControl() para instanciar el objeto en función de la iteración:
Dim EtiquetaLabel As Label
Dim DatosGridView As GridView
Dim dt As DataTable
Dim id As Integer
Select Case e.Item.ItemType
Case ListItemType.Item, ListItemType.AlternatingItem
id = CInt(CType(Repeater1.DataSource, ArrayList).Item(e.Item.ItemIndex))
' Se rellena el DataTable que obtenemos a partir del elemento del ArrayList
dt = ConsultarPorId(id)
' Se realiza el enlace de los datos, tanto del GridView como del Label.
EtiquetaLabel = CType(e.Item.FindControl("EtiquetaLabel"), Label)
DatosGridView = CType(e.Item.FindControl("DatosGridView"), GridView)
EtiquetaLabel.Text = dt.Rows(0).Item("Nombre").ToString
DatosGridView.DataSource = dt
DatosGridView.DataBind()
End Select
Esto hará que se cargue un GridView y un Label para cada ID (en este caso se trata de IDs, podemos almacenar cualquier tipo de dato en el DataSource), repitiendo el código DataSource.Item.Count veces.
Añadir un tooltip a los elementos de un DropDownList
En ocasiones necesitamos utilizar controles de tipo SELECT cuyo ancho es demasiado pequeño para que su contenido sea completamente visible.
Una solución parcial a este problema es la de agregar un tooltip a cada elemento que resalte el contenido del mismo al pasar el ratón por encima.
Una forma sencilla (pero que desgraciadamente no funciona en todos los navegadores) consiste en agregar el elemento title a cada uno de los elementos option del select.
|
<select name=”Combo”> <option title=”Primer elemento”>Primer elemento</option> <option title=”Segundo elemento”>Segundo elemento</option> <option title=”Tercer elemento”>Tercer elemento</option> <option title=”Cuarto elemento”>Cuarto elemento</option> <option title=”Quinto elemento”>Quinto elemento</option> <option title=”Sexto elemento”>Sexto elemento</option> <option title=”Séptimo elemento”>Séptimo elemento</option> <option title=”Octavo elemento”>Octavo elemento</option> </select> |
Por desgracia, realizar esta opción en HTML puro y duro no resulta demasiado efectivo si queremos cambiar el contenido dinámicamente. Para realizar esta acción es .NET, partiríamos de un control de tipo DropDownList, al que llamaremos, por ejemplo, DropDownListElementos.
| <asp:DropDownList ID=”DropDownListElementos” runat=”server”></asp:DropDownList> |
Rellenaremos el contenido del control asignándole un origen de datos, por ejemplo, un DataTable llamado dt.
|
DropDownListElementos.DataSource = dt; DropDownListElementos.DataValueField = dt.Columns[0].ColumnName; DropDownListElementos.DataTextField = dt.Columns[1].ColumnName; DropDownListElementos.DataBind(); |
Ahora que nuestro DropDownList contiene elementos, añadiremos de forma dinámica el atributo title a cada uno de sus elementos.
|
if (DropDownListElementos != null) foreach (ListItem li in DropDownListElementos.Items) li.Attributes.Add(“title”, li.Text); |
Hecho esto, se añadirá, por ejemplo, en el método Load de la página que deseemos incluir este atributo, justo después de haber rellenado los elementos del DropDownList.

Title de un elemento de un SELECT

