jueves, 28 de mayo de 2009

Recorrer los nodos de un TreeView control desde javascript

Hace unos dias me surgio la necesidad de trabajar con el control treeview, mas concretamente he tenido que realizar una busqueda sobre sus nodos. Para llevar a cabo esta tarea tenia que recorrer todo el arbol y comprobar si el valor de alguno de los nodos coincidia con el texto que un usuario introduciria en una caja de texto. Esta tarea me ha llevado a investigar mas profundamente el control Treeview, es un cotrol digamos... diferente. Para recorrer el control primero de todo he tenido que fijarme en el html que se genera, este esta compuesto por capas y tablas. Un nodo es una tabla con una fila y dentro de esas filas celdas, que correspoden con la imagen de expandir colarpsar, la imagen que el nodo tenga y el nombre o texto del nodo. Si este nodo tiene nodos hijos, estos iran dentro de una tabla cada uno de ellos y todos ellos dentro de una etiqueta
que por identificador tendra el del nodo padre más un el sufijo "Nodes". Basandonos en esto el código seria el siguiente: //obtención de la cadena a buscar var keysrch = $get('<%=txtBuscar.ClientID %>').value; //obtencion del objeto Treeview var tree = document.getElementById('<%=arbolListines.ClientID%>'); if(keysrch != '') { //obtencion de todas las tablas que hay dentro del control var tables = tree.getElementsByTagName('table'); if(tables) { for (var i = 0, j = tables.length; i < j; i++) { //dentro de cada tabla accedemos a los enlaces que esta continen links = tables[i].getElementsByTagName('a'); if(links) { for (var x = 0, y = links.length; x < y; x++) { //si el primer nodo no es una imagen significa que no es ni el icono +/- //tampoco es la imagen que hemos asociado a nuestro nodo, con lo que ya hemos //llegado a la posición en la que se encuentra el texto que es lo que nos interesa if(links[x].firstChild.nodeName.toLowerCase() !='img') { // procesamos el texto para buscar si la cadena que de búsqueda esta dentro del nombre del nodo var result = links[x].innerHTML.toLowerCase().indexOf(keysrch); if (result != -1) { //hemos encontrado el nodo que buscabamos //procesar..... }//fin del if que comprueba que estemos buscando solo en el enlace que contiene el nombre } }//fin del bucle for que recorre todos los enlaces de cadad nodo } }//fin del bucle for que recorre las tablas que genera el control treeview en HTML }

miércoles, 20 de mayo de 2009

Cachear imagenes creadas en un HttpHandler

Existen varias maneras de mejorar el rendimiento de una aplicación web, una de las más importantes es el cacheo de datos y más concretamente, cachear imagenes. Existen algunos escenarios en los cuales conseguir cachear los datos no es trivial, uno de ellos es cuando tenemos una imagen almacenada en una base de datos en formato BLOB, en este casi si queremos mostrar la imagen en nuestra web, una manera de hacerlo es creando un Controlador genérico (.ashx). Si hacemos esto deberemos manejar manualmente el cacheo de imagenes. El siguiente fragmento de código muestra como habilitar la cache:

//creacion de un objeto TimeSpan que va a indicar la duración de la cache

TimeSpan freshness = new TimeSpan(0, 0, 10, 0);

//se configura el tiempo de expiración de la cache

context.Response.Cache.SetExpires(DateTime.Now.Add(freshness));

//configuracion del ámbito de la cache

context.Response.Cache.SetCacheability(HttpCacheability.Public);

context.Response.Cache.SetValidUntilExpires(false);

Posteriormente se se envia la salida de la imagen

context.Response.ContentType = "image/gif";

context.Response.OutputStream.Write(buffer, 0, buffer.Length);

martes, 19 de mayo de 2009

Como saber si si ha ocurrido un Postback Asíncrono Parcial

Con la llegada Ajax debemos tener en cuenta que actualmente existen dos tipos de Postback, uno podriamos llamarlo Full Postback, en él se recarga toda la página. Con ajax surge el concepto de Partial Postback, es una ida al servidor que solo actualiza una parte de la página. En ocasiones puede ser interesante para el control de nuestras aplicaciones si un Postaback ha sido parcial o total, para ello tendremos que obtener una instancia del ScriptManager de nuestra página a traves del método GetCurrent y comprobando el valor de la propiedad IsInAsyncPostBack. A continuación podemos ver un ejemplo: protected void Page_Load(object sender, EventArgs e)

{

if (Page.IsPostBack)

{

//Se obtiene comprueba la propiedad IsInAsyncPostBack

if (ScriptManager.GetCurrent(this.Page).IsInAsyncPostBack)

{

// TODO logica para una recarga parcial

}

else

{

//logica para un postback total

}

}

}

jueves, 14 de mayo de 2009

Enlazar un enumerado a un Dropdownlist c#

En muchas ocasiones en nuestras aplicaciones definimos enumerados para hacer un manejo mas eficiente de los datos, muchas veces queremos mostrarlos en un combo para que el usuario seleccione. Para hacer esto podemos enlazar el enumerado al control DropdownList public enum MiEnumerado {Lunes,Martes,Miercoles} MiDropDownList.DataSource = Enum.GetNames(typeof(MiEnumerado)); MiDropDownList.DataBind(); Para acceder al valor seleccionado podriamos hacerlo de la siguiente manera: MiEnumerado miEnun = (MiEnumerado)Enum.Parse(typeof(MiEnumerado),MiDropDownList.SelectedValue); De esta forma tenemos el valor seleccionado en forma de enumerado nuevamente.

martes, 12 de mayo de 2009

Ciclo de vida de una pagina Asp.Net

Gracias a un gran compañero y mejor profesional (para que no te quejes Rafa) os dejo el esquema del ciclo de vida completo de una pagina asp.net.
(Haz click en la imagen para verla a tamaño completo)

Saber que control ha provocado el Postback

En algunas ocasiones nos gustaria saber control ha provocado la recarga (postback) de la página para esto podemos hacerlo de dos formas dependiendo de si es una recarga parcial (ajax) o un postaback total de la pagina. 1.-Si es una recarga parcial de la pagina //obtenemos la página actual Page page = (HttpContext.Current.Handler as Page); //mediante el Scriptmanager accedemos al control que ha hecho la recarga parcial de la misma string ctrlname = ScriptManager.GetCurrent(page).AsyncPostBackSourceElementID; Control control = page.FindControl(ctrlname); 2.-Si es una recarga total ctrlname = page.Request.Params["__EVENTTARGET"]; Esto funciona conrrectamente con casi todos los controles pero No con Botones, esto es debido a que los botons cuando se pintan en html no llaman a la función __doPostBack de Javascript y por tanto __EVENTTARGET nunca va a tener valor, para conseguir esto os dejo un enlace en el que muestran como conseguirlo para todo tipo de controles. Es un articulo muy útil de Ryan Farely.

Determining the Control that Caused a PostBack

lunes, 11 de mayo de 2009

TreeView SelectedNodeStyle no funciona sin Postback

Después de pasar un buen rato trabajando con el control Treview de asp.net (la version 2.0 del control, con la uno este problema no existe) me surgio un problema que con el que no contaba, el árbol que yo estaba generando no hacia postback cuando se producia un click en uno de los nodos, este que a priori no deberia suponer un problema, lo es cuando queremos personalizar el estilo del nodo seleccionado, en esta situación no se aplicaba el estilo. Esto se puede hacer de forma declarativa medienta las propiedades SelectNodeStyle. <"asp:treeview id="arbolListines" runat="server" backcolor="Aqua" bordercolor="Black" bold="true" > Para que el estilo sea reconocido de forma correcta debemos añadir la siguiente propiedad al control Treeview: Target="_self" De esta forma conseguiemos que funcione correctamente.

Acceder a un control dentro de un ContentPlaceHolder desde JavaScript

Un pequeño problema a la hora de usar las MasterPage es que al introducir controles dentro de los ContentPlaceHolder, el ClientId de estos controles aparece modificado, se le añade un prefijo con el nombre de su contenedor (ContentPlaceHolder). Esto solo nos afecta si queremos acceder a estos controles desde el cliente (javascript) . Un ejemplo seria un TextBox con el Id = txtNombre, este apareceria en nuestro codigo html como
ctl00_ContentPlaceCuerpoPagina_txtNombre

La solución fácil seria acceder usando el nombre completo

document.getElementById("ctl00_ContentPlaceCuerpoPagina_txtNombre").value

Esto seria poco elegante y ademas peligroso, ya que si en algun momento se cambia el nombre
del ContentPlaceHolder,esa sentencia ya no seria valida. Una forma efectiva de acceder al control seria.


document.getElementById('<%=txtNombre.ClientID %>').value