Redimensionar un control de texto con el tamaño de su contenido
En ocasiones, trabajando con WinForms, nos encontramos con un control contenedor de un texto variable en el que, o nos sobra espacio o nos falta. La clase Graphics de System.Drawing nos proporciona un método tremendamente útil para saber el tamaño, en píxels, de una cadena de texto.
Veremos a continuación cómo redimensionar de forma dinámica un control dependiendo del tamaño del texto contenido. Para ello crearemos, por ejemplo, un TextBox al que llamaremos txtPrueba, y en el que albergaremos un texto, por ejemplo “Más vale pájaro en mano, que ciento volando”.
txtPrueba.Text = "Más vale pájaro en mano que ciento volando";
A continuación, declararemos dos variables enteras, una para el alto y otra para el ancho.
// Declaramos una variable entera para almacenar el nuevo ancho y el nuevo alto int nuevoAncho = 0; int nuevoAlto = 0;
Es ahora donde instanciaremos la clase Graphics a partir del control TextBox, y extraeremos la fuente que está utilizando.
// Creamos un objeto de tipo Graphics a partir del TextBox Graphics g = txt.CreateGraphics(); // Extraemos la fuente del TextBox Font fuente = txt.Font;
Obtenemos, a partir del objeto Graphics, su alto y ancho a partir del método MeasureString, que no hace otra cosa que medir, en pixels, el tamaño que ocupa la cadena con la fuente indicada.
nuevoAncho = (int)g.MeasureString(txt.Text, fuente).Width; nuevoAlto = (int)g.MeasureString(txt.Text, fuente).Height;
Por último, asignamos los nuevos valores de alto y ancho y refrescamos el control.
txt.Width = nuevoAncho; txt.Height = nuevoAlto; txt.Refresh();
A partir de estos conceptos básicos, se pueden encontrar multitud de utilidades a este proceso, como por ejemplo, redimensionar el desplegable de un ComboBox al tamaño del mayor de sus elementos.
Utilizar la Base de Datos como repositorio de imágenes (II)
En un artículo anterior aprendimos a almacenar una imagen en nuestra base de datos SQL Server. Ahora vamos a obtener la imagen que almacenamos previamente utilizando como dirección de la imagen un formulario aspx al que le pasaremos el identificador de la imagen a través de la QueryString.
Comenzaremos creando un nuevo formulario, al que llamaremos showImage.aspx. En el formulario, crearemos un nuevo método al que llamaremos ObtenerImagen, que recibirá como parámetro un entero (el ID de la imagen) y devolverá una secuencia de bytes (un byte[]).
byte[] ObtenerImagen(int idImagen)
{
}
Lo primero que hará este método será declarar una cadena de conexión y una sentencia SELECT que devuelva la imagen cuyo ID le pasamos. Para ello, declararemos ambas cadenas de texto.
string selectCommandText = "SELECT Fichero FROM Imagen WHERE IdImagen = " + Convert.ToString(idImagen); string ConnectionString = @"Data Source=DANIGARCIA\SQLSERVER2005;Initial Catalog=TestDB;Persist Security Info=True;User ID=dani;Password=c0ntr4s3n14";
A continuación podemos hacer dos cosas: crear un SqlCommand y ejecutar la sentencia SELECT, o bien declarar un DataSet y un SqlDataAdapter y dejar que sea éste último objeto el que nos proporcione los datos. Optaremos por la segunda opción, que pese a ser menos óptima, resulta mucho más cómoda
// Declaramos un DataSet y un SqlDataAdapter DataSet ds = new DataSet(); SqlDataAdapter adapter = new SqlDataAdapter(selectCommandText, selectConnectionString); // Rellenamos el DataSet con la consulta y la cadena de conexión anteriores adapter.Fill(ds);
Llegados a este punto, ya deberíamos tener almacenada en el DataSet la imagen que estábamos buscando. Por lo tanto, lo único que deberemos hacer será serializarla y devolverla, realizando las comprobaciones pertinentes:
if ((ds != null) && (ds.Tables.Count > 0) && (ds.Tables[0].Rows.Count > 0))
{
if (!ds.Tables[0].Rows[0].IsNull("Fichero"))
{
return ((byte[])(ds.Tables[0].Rows[0]["Fichero"]));
}
}
return null;
Llegados a este punto, codificaremos el contenido del Page_Load de nuestro aspx, comprobando la QueryString y pasándole el parámetro a nuestra función ObtenerImagen, declarando, en primer lugar, un array de Bytes para almacenar el resultado:
protected void Page_Load(object sender, EventArgs e)
{
byte[] bImagen = null;
if (!string.IsNullOrEmpty(Convert.ToString(Request.QueryString["id"])))
{
bImagen = ObtenerImagen(Convert.ToInt32((Convert.ToString(Request.QueryString["id"]))));
}
Si el resultado obtenido no es nulo, modificamos la respuesta para que sea de tipo imagen, haciendo lo siguiente:
if(bImagen != null)
{
Response.Clear();
Response.Buffer = true;
Response.ContentType = "image/jpeg";
Response.BinaryWrite(bImagen);
Response.End();
}
}
Con lo cual, si invocamos la ruta a través del ID, obtendremos directamente una imagen:
Esto es una prueba <br /> <img src="../aspx/showImage.aspx?id=1" />
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.
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.
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.

Implementación de interfaces en C#
Una técnica imprescindible para lograr un adecuado nivel de abstracción es la utilización de interfaces.
Hablando en llano, una interfaz no es más que una estructura de datos que muestra únicamente las firmas de los métodos de una clase. A partir de ahí, una clase que herede de la interfaz estará obligada a “rellenar” la implementación de dichos métodos. De forma simple, una interfaz sería algo así:
Interfaz Motor
Arrancar();
Detener();
Abstracción de datos (III): Utilizando Reflection para implementar un DAO en C#
El siguiente paso de nuestro objetivo de lograr un nivel de abstracción decente a la hora de implementar un modelo de datos consiste en la utilización del espacio de nombres Reflection. En una entrada anterior mostrábamos una función que nos devolvía un diccionario que contenía tanto el nombre como el valor de los filtros de la consulta.
Hoy vamos a ir más allá. Vamos a olvidarnos de la codificación de un DTO concreto: codificaremos un DAO que espere un objeto DTO genérico que cumpla los siguientes requisitos:
- Cada Propiedad se corresponderá con un campo de la fuente de datos.
- El nombre de la clase será DTO + Nombre de la tabla
Con estos dos requisitos, podremos codificar un DAO que comienza a abstraerse de los datos en sí, ligándose únicamente a una estructura arquitectónica y a una fuente de datos concreta (SQL Server). El siguiente paso será eliminar la segunda de estas restricciones, como veremos posteriormente.
Es importante partir de la entrada anterior para entender esta entrada, ya que no escribiré todo el código, sino que mostraré únicamente las modificaciones necesarias a los ficheros anteriores para poder entender el ejemplo.
DTOUsuario
La clase DTOUsuario no sufrirá modificación alguna. Esto es, será el DAO el que se adapte para conseguir la abstracción de un DTO en concreto.
DAOGenerico
En lugar de implementar las sentencias simples (SELECT, INSERT, UPDATE, DELETE) en cada uno de los DAO, crearemos una clase base llamada DAOGenerico en la que crearemos estas operaciones comunes. Posteriormente, las clases que hereden de ésta implementarán métodos específicos para cada entidad.
El primer cambio que tenemos en esta clase es la presencia de las funciones ObtenerElementos (visto en el primer post dedicado a Reflection) y ObtenerOrdenSql (vista en la anterior parte). Codificadas ambas funciones (manteniéndolas intactas), veremos cómo cambiamos la función select. El cuerpo de la misma será el siguiente:
public DataSet select(object datos)
Vemos que ya no esperamos un DTOUsuario, sino que nos basta un objeto cualquiera.
El siguiente paso será declarar los mismos elementos que en la versión anterior, así como comprobar que el objeto recibido no es nulo.
// Instanciamos un DataSet, que albergará el contenido de la consulta
DataSet ds = new DataSet();
// Declaramos dos StringBuilders: uno para la sentencia y otra para los campos
// A su vez, declaramos un ArrayList para almacenar los parámetros.
StringBuilder SQLString = new StringBuilder();
StringBuilder Campos = new StringBuilder();
ArrayList Parametros = new ArrayList();
String NombreTabla = "";
// Comprobamos que el DTO exista
if (datos == null)
throw new NullReferenceException("GenericDAO.select(datos)");
A continuación, recorremos los elementos del DTO, añadiendo los filtros en el caso de que éstos existan. Recordemos que Reflection nos proporcionaba la funcionalidad necesaria para almacenar en un diccionario el nombre y el valor de cada propiedad del objeto.
Dictionary<string , object> coleccionDatos = new Dictionary</string><string , object>(); // Obtenemos todas las propiedades del objeto coleccionDatos = ObtenerElementos(datos, MemberTypes.Property);
Ahora iteraremos cada elemento del diccionario, añadiendo, como hacíamos antes, elementos del tipo “Filtro = @Filtro”, solo que ahora el nombre del filtro viene dado por la clave del diccionario y su valor, por el contenido de el elemento que corresponde a esa clave.
if (coleccionDatos != null)
{
foreach (string key in coleccionDatos.Keys)
{
if (coleccionDatos[key] != null)
{
Campos.Append(key).Append(" = @").Append(key).Append(" AND ");
Parametros.Add(new SqlParameter("@" + key, coleccionDatos[key]));
}
}
}
Como última novedad, obtendremos el nombre de la tabla a partir del nombre de la clase, eliminando del principio el prefijo “DTO”.
// Creamos la cláusula SELECT
SQLString.Append("SELECT * FROM ").Append((datos.GetType()).Name.TrimStart("DTO".ToCharArray()));
El resto del método es igual a la versión anterior.
// Añadimos la cláusula WHERE, en caso de que sea necesaria
if (Campos.Length > 0)
{
SQLString.Append(" WHERE ");
// Como la cadena acabará en 'AND ', eliminamos los últimos 4 caracteres para cerrar la sentencia
SQLString.Append(Campos.ToString().Substring(0, Campos.ToString().Length - 4));
}
// Obtenemos un SqlCommand configurado al efecto
SqlCommand orden = ObtenerOrdenSql(SQLString.ToString(), Parametros);
// Instanciamos un SqlDataAdapter y efectuamos la consulta
SqlDataAdapter da = new SqlDataAdapter(orden);
da.Fill(ds);
// Por último, devolvemos el DataSet
return ds;
Hecho esto, podemos crear un DTO por cada tabla de la base de datos. Siempre y cuando cumplamos las normas de respetar los nombres de tabla y columnas, esta función devolverá la consulta apropiada a cada entidad DTO llamando a la función select() y pasándole el objeto DTO como parámetro.
Introducción a Reflection: Recorriendo los elementos de un objeto
La reflexión es un proceso por el cual se posibilita observar y modificar la estructura y comportamiento de un objeto. Utilizar reflexión para programar implica un grado de abstracción enorme, y su complejidad es relativamente elevada.
La reflexión es soportada por multitud de lenguajes, y se aprovecha de la posibilidad de tratar a las instrucciones como datos. Generalmente se utiliza con el objetivo de observar o modificar el estado o el comportamiento de un programa en tiempo de ejecución. Es, por tanto, la base de la metaprogramación.
El Framework .NET posee un espacio de nombres dedicado a esta filosofía: System.Reflection. Veremos un pequeño ejemplo de cómo podemos, por ejemplo, obtener información sobre un objeto en concreto, como el nombre de sus elementos y su contenido.
La clase Dictionary
Las colecciones de datos, incluidas en los espacios de nombres System.Collections y System.Collections.Generic nos permiten agrupar datos de forma más eficiente de lo que nos permitiría, por ejemplo, un Array.
Las estructuras de este espacio de nombres más utilizadas suelen ser los Hashtable (pares clave-valor) y los ArrayList (Arrays de objetos heterogéneos). No obstante, y a nivel personal, una de las colecciones de datos que más potentes me parecen es la clase Dictionary.
Esta clase, al igual que el Hashtable, permite almacenar pares clave-valor. La diferencia está en que, a diferencia del Hashtable, la clave puede ser del tipo que nosotros escojamos (un entero, una estructura, o incluso una clase). Además, es posible acceder tanto a la lista de claves como a la de valores. Por tanto, al crear un diccionario le proporcionaremos la información del tipo de la clave y el tipo del valor.
Para nuestro ejemplo, crearemos un diccionario de tipo (string, object), es decir, un diccionario en el que la clave sea una cadena de texto y el valor sea un objeto.
Obteniendo información sobre un objeto.
Conociendo la clase Dictionary, es hora de declarar el cuerpo de la función que vamos a codificar. Se tratará de una función que recibirá dos parámetros: un objeto y un MemberType. El MemberType no es más que el tipo de miembro que queremos obtener del objeto (método, propiedad, etc.). Por lo tanto, el cuerpo de nuestra función será el siguiente:
private Dictionary<string , object> ObtenerElementos(object objeto, MemberTypes TipoElemento)
{
}
No debemos olvidarnos, eso sí, de incluir los espacios de nombres System.Reflection y System.Collections.Generic para poder hacer uso de la clase Dictionary y de Reflection, respectivamente.
Comenzaremos por declarar un diccionario de tipo (string, object).
Dictionary</string><string , object> Elementos = new Dictionary</string><string , object>();
A continuación, recorreremos la información de cada elemento del objeto con un bucle foreach. Para ello utilizaremos la clase MemberInfo.
foreach (MemberInfo infoMiembro in objeto.GetType().GetMembers())
{
}
En el interior del bucle, comprobaremos si el tipo del objeto es el que nosotros buscamos, y si es así, lo insertaremos en nuestro diccionario.
if (infoMiembro.MemberType == TipoElemento)
{
if ((PropertyInfo)infoMiembro != null)
Elementos.Add(((PropertyInfo)infoMiembro).Name, ((PropertyInfo)infoMiembro).GetValue(objeto, null));
}
Como podemos ver, el tipo de miembro puede ser de varios tipos.

Finalmente, el diccionario devolverá los nombres de los elementos junto a sus respectivos valores. Por ejemplo, si buscamos las propiedades del objeto, le pasaríamos a la función como segundo parámetro MemberTypes.Property. Si el objeto tuviera una propiedad llamada “IdUsuario” cuyo valor fuese 1, el diccionario guardaría una entrada (“IdUsuario”, (object)1).
El método completo sería el siguiente:
/// <summary>
/// Función encargada de devolver un tipo de elemento en concreto de un objeto en un conjunto
/// de pares clave - valor.
/// </summary>
/// <changelog>
/// Daniel García 15/05/2009 Creación
/// </changelog>
private Dictionary</string><string , object> ObtenerElementos(object objeto, MemberTypes TipoElemento)
{
try
{
// Declaramos un Diccionario que contendra el nombre de los elementos del objeto y el
//contenido de cada elemento.
Dictionary</string><string , object> Elementos = new Dictionary</string><string , object>();
// Se recorren los miembros del objeto
foreach (MemberInfo infoMiembro in objeto.GetType().GetMembers())
{
// Si el tipo del objeto es del tipo que buscamos, se añade al diccionario
if (infoMiembro.MemberType = TipoElemento)
{
if ((PropertyInfo)infoMiembro != null)
Elementos.Add(((PropertyInfo)infoMiembro).Name, ((PropertyInfo)infoMiembro).GetValue(objeto, null));
}
}
return Elementos;
}
catch (Exception ex)
{
throw (ex);
}
}
Posteriormente encontraremos una utilidad práctica a esta función, aplicándola a nuestro patrón DAO para no tener que depender de los nombres de los campos. Esta sencilla función ayudará a aumentar muchísimo el nivel de abstracción e independencia de nuestra aplicación.
NOTA: Parece que WordPress sustituye de forma interna la estructura Dictionary<string, object> por Dictionary</string><string, object>. Hay que tener en cuenta este fallo a la hora de la codificación. Disculpen las molestias.

