Teoria Ajax y Aspnet

79
AJAX y ASP.NET Tema 10 Inadeco AJAX

Transcript of Teoria Ajax y Aspnet

Page 1: Teoria Ajax y Aspnet

AJAX y ASP.NET

Tema 10

Inadeco

AJAX

Page 2: Teoria Ajax y Aspnet

AJAX y ASP.NET

2 1.- Leer Tiempo del Cliente Para obtener el tiempo del cliente necesitamos una función JavaScript.

// JScript File function clientTime() { var t = new Date(); return ( char2(t.getDate()) + "/" + char2(t.getMonth() + 1) + "/" + String(t.getYear()).substring(4,2) + " " + char2(t.getHours()) + ":" + char2(t.getMinutes()) + ":" + char2(t.getSeconds())); } function char2(v) { if ((v >= 0) && (v <= 9)) return "0" + v; else return v; } Para programar un evento de temporizador del lado del cliente en una página web, JavaScript suministra un esquema sencillo, se activa un procedimiento invocando el método setTimeout del objeto window, el cual usa como parámetros el nombre de la función que se va a llamar, y el tiempo en milisegundos de espera para hacer la llamada. Hacemos la primera llamada desde el evento de carga de la página, normalmente “body onload” o un “Page Load”. Para hacer el temporizador continuo, la función que se invoca en setTimeout debe llamar nuevamente a setTimeout. Por último si queremos mostrar el resultado en la pagina, desde unas líneas escribimos en un control del lado del cliente. En el siguiente ejemplo el tiempo del cliente se muestra en una caja de texto de html de nombre “txtClientTime”. Finalmente el código de la página es el siguiente:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="tiempodelcliente._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 runat="server"> <title>Tiempo del Cliente</title> <script type="text/javascript" src="ClientTime.js"></script> <script type="text/javascript"> // activando un "Timer" function timerEvent() { showClientTime(); // hace continuo el Timer window.setTimeout("timerEvent()", 1000); } function showClientTime() { t = clientTime(); var r = document.getElementById("txtClientTime"); r.value = t; } </script>

Page 3: Teoria Ajax y Aspnet

AJAX y ASP.NET

3 </head> <body onload="window.setTimeout('timerEvent()',1500);"> <form id="form1" runat="server"> <div> <span>Tu Hora: </span> <input id="txtClientTime" type="text" style="width: 200px" /> </div> </form> </body> </html>

Siempre que se quieran datos del cliente es necesario recurrir a código del lado del cliente.

2.- Leer tiempo del Servidor con PostBack Leer el tiempo del servidor en un postback no requiere mucha discusión. Solo necesitamos un control asp con postback. En el código del lado del servidor leemos el retorno de la función DateTime.Now(). Si queremos mostrarla en un control la asignamos directamente. Ejemplo, usamos un botón btnServerTime y una caja de texto txtServerTime:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="tiempodelservidorconpostback._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 runat="server"> <title>Tiempo del servidor con postback</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button ID="btnServerTime" runat="server" onclick="btnServerTime_Click" Text="Dame la hora" /> <asp:TextBox ID="txtHora" runat="server"></asp:TextBox> </div> </form> </body> </html>

3.- Instalación de AJAX con ASP.NET

3.1.- Requisitos de Sistema

Sistemas Operativos • Windows 2003 Server • Windows XP • Windows Vista • Otras Versiones que soporten .NET Framework 2.0

Page 4: Teoria Ajax y Aspnet

AJAX y ASP.NET

4 Software Requerido

• .NET Framework 2.0 o 3.0 • IE 5.0 o posterior

Software Opcional • Visual Studio 2005 • Visual Web Developer Express Edition

3.2.- Pasos de la Instalación 1. Derechos de Administrador de la máquina 2. Desinstalar versiones anteriores de ASP.NET AJAX 3. Descargar ASPAJAXExtSetup.msi

http://www.asp.net/ajax/default.aspx 4. Instalar ASPAJAXExtSetup.msi

Una vez instalado, ya contaremos con novedades en el Visual Studio 2005

Page 5: Teoria Ajax y Aspnet

AJAX y ASP.NET

5

Page 6: Teoria Ajax y Aspnet

AJAX y ASP.NET

6 5. Descargar ASP.NET AJAX Control Toolkit

6. Instalar ASP.NET AJAX Control Toolkit

3.3.-Introducción a ASP.NET AJAX Componentes relacionados con las posibilidades de AJAX en ASP.NET:

• Microsoft AJAX Library es un conjunto de archivos de JavaScript que hacen fácil la programación de JavaScript del lado del cliente. Incluye soporte para clases, espacios de nombre, eventos, tipos de datos, etc. También soporta manejo de errores, depuración, y globalización. La librería combina JavaScript y DHTML. La librería es usada por ASP.NET y los Ajax Control Toolkit. Sin embargo, también podemos aprovechar la librería para ampliar nuestros propios controles con comportamientos de JavaScript.

• Controles de Servidor ASP.NET AJAX. Son controles de servidor que podemos colocar en las páginas ASP.NET, para realizar actualizaciones parciales de página, comunicaciones con un proceso del servidor para indicar el progreso, y actualizar periódicamente porciones de página.

• AJAX CONTROL TOOLKIT. Es un conjunto de controles que muestran el poder de AJAX. Estos controles pueden ser usados en nuestras páginas web. Cajas con mascaras, sliders, filtros, pop-up, etc. Es una extensión para Visual Studio y ASP.NET. http://www.asp.net/ajax

• Soporte Servicios Web del lado del cliente. Proporciona soporte para llamadas a servicios web de manera asíncrona desde el cliente usando JSON y XML

3.4.- Usos y Beneficios de ASP.NET AJAX Las características de ASP.NET AJAX proveen una experiencia de usuario más rica que la de las aplicaciones web estándar:

Page 7: Teoria Ajax y Aspnet

AJAX y ASP.NET

7 • Actualizaciones parciales de página. Permite definir un área que debería actualizarse y

realizar Postback. • Procesar del lado del cliente. Proporciona interactividad, información inmediata y

capacidad de respuesta a los usuarios. • UI como aplicación de escritorio. Provee a los usuarios cajas de dialogo modal,

indicadores de progreso, máscaras, tooltips, etc. • Indicadores de Progreso. Permite mostrar el progreso de un proceso del lado del

servidor y actualización continua en el usuario. • Mejora del rendimiento. Podemos incrementar el rendimiento procesando partes de

una página en el cliente. • Llamadas desde el cliente a un servicio web. Permite llamadas al servidor

directamente desde script del cliente

4.- Leer Tiempo del Servidor usando AJAX ASP.NET Para resolver el problema bastan tres controles del servidor de Ajax ASP.NET : ScriptManager, Update Panel y Timer.

ScriptManager. Es requerido en toda página potenciada con AJAX. UpdatePanel. Es un contenedor especializado en manejar el refresco parcial de la página y evitar el efecto postback. El panel se actualiza en acción a un disparador, Trigger que no es más que otro elemento el cual tiene codificado la acción, ya sea un evento o el cambio de una propiedad de un control de la página que hará que se actualice el contenido del panel de AJAX. TimerControl. Es un control de AJAX que suministra un objeto temporizador entre la página web y el servidor. Anteriormente, un temporizador del lado del servidor en paginas ASP.NET era una cuestión inverosímil o demasiado laboriosa.

%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="tiemposervidorAJAX._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 runat="server"> <title>Página sin título</title> </head> <body> <form id="form1" runat="server"> <h2> Tiempo del Servidor con Atlas</h2> <hr /> <div> <asp:ScriptManager runat="server" id="sm" enablepartialrendering="true" /> <asp:Timer runat="server" id="tmrServerTime" interval="1500" ontick="tmrServerTime_Tick" /> <asp:UpdatePanel id="up1" runat="server"> <Triggers> <asp:AsyncPostBackTrigger ControlID="tmrServerTime" EventName="Tick" /> </Triggers> <ContentTemplate> <asp:TextBox ID="txtServerTime" runat="server" Width="220px" />

Page 8: Teoria Ajax y Aspnet

AJAX y ASP.NET

8 </ContentTemplate> </asp:UpdatePanel> </div> <div> <input id="txtClientTime" type="text" style="width: 220px" runat="server" /> </div> <hr /> </form> </body> </html>

La respuesta del evento temporizador se recibe en el servidor. Sorprendentemente, se puede asumir el temporizador casi de la misma forma que en una aplicación Windows.

protected void tmrServerTime_Tick(object sender, EventArgs e) { this.txtServerTime.Text = DateTime.Now.ToString("dd/mm/yy hh:mm:ss"); }

5.- Controles de Servidor de AJAX

6.- Control ScriptManager El control ScriptManager administra el script de cliente para las páginas web habilitadas para ASP.NET AJAX. De forma predeterminada, el control ScriptManager registra el script para Microsoft AJAX Library con la página. Esto permite a los script de cliente usar las extensiones del sistema tipo y admitir algunas características, como la representación parcial de páginas y las llamadas de servicio web.

Control principal de la infraestructura de servidor de ASP.NET AJAX. Ninguna funcionalidad de AJAX puede ser habilitada en las páginas ASPNET AJAX sin que se haga referencia a este control.

Page 9: Teoria Ajax y Aspnet

AJAX y ASP.NET

9 Debe usar un control ScriptManager en una página para habilitar las siguientes características AJAX de ASP.NET:

• Funcionalidad de script de cliente de Microsoft AJAX Library y todos los scripts personalizados que desee enviar al explorador.

• La representación parcial de páginas, que permite actualizar partes de la página de forma independiente sin que exista ninguna devolución de datos. Los controles UpdatePanel, UpdateProgress y Timer de ASP.NET requieren un control ScriptManager para admitir la representación parcial de páginas.

• Las clases de proxy JavaScript para los servicios web, que permiten usar scripts de cliente para tener acceso a servicios web y métodos marcados especialmente en las páginas ASP.NET. Para ello, expone los servicios web y los métodos de página como objetos con establecimiento inflexible de tipos.

• Clases JavaScript para obtener acceso a los servicios de aplicación de autenticación, perfiles y funciones de ASP.NET.

<asp:ScriptManager runat="server" id="sm" enablepartialrendering="true" />

7.- ScriptManagerProxy El control ScriptManagerProxy permite que los componentes anidados, como páginas de contenido y controles de usuario, agreguen a las páginas referencias a scripts y servicios cuando ya se ha definido un control ScriptManager en un elemento primario.

Una página web sólo puede contener un control ScriptManager, bien de forma directa en la propia página, o de forma indirecta en un componente anidado o primario. El control ScriptManagerProxy permite agregar scripts y servicios a páginas de contenido y controles de usuario donde la página maestra o la página host ya contienen un control ScriptManager.

Cuando se usa el control ScriptManagerProxy, puede agregar las colecciones de scripts y servicios definidas por el control ScriptManager. Si no desea incluir scripts y servicios específicos a cada página que incluya un control ScriptManager determinado, quítelos del control ScriptManager y agréguelos a páginas individuales mediante el control ScriptManagerProxy.

8.- El Control UpdatePanel Los controles de ASP.NET UpdatePanel permiten generar aplicaciones web enriquecidas y centradas en el cliente. Mediante el uso de los controles UpdatePanel, se pueden actualizar partes seleccionadas de la página en lugar de actualizar toda la página con una devolución de datos. Esto se conoce como actualización parcial de la página. Una página web ASP.NET que

Page 10: Teoria Ajax y Aspnet

AJAX y ASP.NET

10 contiene un control ScriptManager y uno o varios controles UpdatePanel puede participar automáticamente en las actualizaciones parciales de la página, sin un script de cliente personalizado.

El control UpdatePanel es un control de servidor que ayuda a desarrollar páginas web con un comportamiento de cliente complejo que hace que una página web parezca más interactiva al usuario final. Normalmente, escribir código que se coordine entre el servidor y el cliente para actualizar sólo las partes especificadas de una página web requiere un conocimiento detallado de ECMAScript (JavaScript). Sin embargo, mediante el uso del control UpdatePanel, puede hacer que una página web participe en las actualizaciones parciales de página sin necesidad de escribir ningún script de cliente. Si lo desea, puede agregar el script de cliente personalizado para mejorar la experiencia del usuario cliente. Cuando se usa un control UpdatePanel, el comportamiento de la página es independiente del explorador y puede reducir la cantidad de datos que se transfieren entre el cliente y el servidor.

Los controles UpdatePanel trabajan especificando las regiones de una página que se pueden actualizar sin actualizar la página entera. Este proceso se coordina mediante el control de servidor ScriptManager y la clase de cliente PageRequestManager. Cuando las actualizaciones parciales de la página están habilitadas, los controles pueden enviar al servidor de forma asincrónica. Una devolución de datos asincrónica se comporta como una devolución de datos normal en cuanto que la página de servidor resultante ejecuta la página completa y controla el ciclo de vida. Sin embargo, con una devolución de datos asincrónica, las actualizaciones de la

Page 11: Teoria Ajax y Aspnet

AJAX y ASP.NET

11 página se limitan a las regiones de la página que están incluidas en los controles UpdatePanel y que están marcadas para actualizarse. El servidor envía el marcado HTML al explorador sólo para los elementos implicados.

Habilitar actualizaciones parciales de página

El control UpdatePanel requiere un control ScriptManager en la página web. De forma predeterminada, las actualizaciones parciales de la página están habilitadas porque el valor predeterminado de la propiedad EnablePartialRendering del control ScriptManager es True.

Especificar el contenido del control UpdatePanel

Puede agregar contenido a un control UpdatePanel colocándolo en el panel de la vista Diseño. Por ejemplo, puede arrastrar otros controles ASP.NET y HTML al panel, y situar el cursor en el panel y escribir directamente en él. Cuando agrega contenido a un control UpdatePanel en la vista Diseño, automáticamente se agregan las etiquetas requeridas <ContentTemplate></ContentTemplate> alrededor del contenido. Si agrega contenido a un control UpdatePanel en la vista Código en lugar de la vista Diseño, debe agregar las etiquetas <ContentTemplate></ContentTemplate> manualmente si no existen ya; de lo contrario, el contenido no se representará en el control UpdatePanel.

Cuando se representa por primera vez una página que contiene uno o varios controles UpdatePanel, se representa todo el contenido de los controles UpdatePanel y se envía al explorador. En las devoluciones de datos asincrónicas posteriores, el contenido de los controles UpdatePanel individuales podría actualizarse. Las actualizaciones dependen de las opciones de configuración del panel, de qué elemento produjo la devolución de datos y del código específico de cada panel.

Especificar los desencadenadores UpdatePanel

De forma predeterminada, cualquier control de devolución de datos dentro de un control UpdatePanel produce una devolución de datos asincrónica y actualiza el contenido del panel. Sin embargo, también puede configurar otros controles de la página para actualizar un control UpdatePanel. Para ello, defina un desencadenador para el control UpdatePanel. Un desencadenador es un enlace que especifica qué evento y qué control de devolución de datos provocan la actualización de un panel. Cuando se provoca el evento especificado del control desencadenador (por ejemplo, un evento Click de un botón), se actualiza el panel de actualización.

Puede crear desencadenadores de un control UpdatePanel mediante el cuadro de diálogo Editor de la colección UpdatePanelTrigger, que se visualiza desde la propiedad Triggers (Desencadenadores) en el panel de tareas Propiedades de etiqueta.

Los eventos de control de los desencadenadores son opcionales. Si no se especifica un evento, el evento desencadenador es el evento predeterminado del control. Por ejemplo, para el control Button, el evento predeterminado es el evento Click.

Cómo se actualizan los controles UpdatePanel

Page 12: Teoria Ajax y Aspnet

AJAX y ASP.NET

12 En la lista siguiente se describen los valores de las propiedades del control UpdatePanel que determinan cuándo se actualiza el contenido de un panel durante la representación parcial de la página:

• Si la propiedad UpdateMode se establece en Always, el contenido de control UpdatePanel se actualiza en todas las devoluciones de datos que se originen en cualquier lugar de la página. Esto incluye las devoluciones de datos asincrónicas de los controles que están dentro de otros controles UpdatePanel y las devoluciones de datos de los controles que no están dentro de los controles UpdatePanel.

• Si la propiedad UpdateMode se establece en Conditional, el contenido del control UpdatePanel se actualiza cuando se da una de las siguientes condiciones:

• Cuando un desencadenador produce la devolución de datos para ese control UpdatePanel.

• Cuando se llama explícitamente al método Update del control UpdatePanel.

• Cuando se anida el control UpdatePanel dentro de otro control UpdatePanel y se actualiza el panel primario.

• Cuando la propiedad ChildrenAsTriggers se establece en True y cualquier control secundario del control UpdatePanel provoca una devolución de datos. Los controles secundarios de los controles UpdatePanel anidados no provocan actualizaciones del control UpdatePanel externo a menos que se definan explícitamente como desencadenadores para el panel primario.

Si la propiedad ChildrenAsTriggers se establece en False y la propiedad UpdateMode se establece en Always, se inicia una excepción. La propiedad ChildrenAsTriggers está diseñada para utilizarse sólo cuando la propiedad UpdateMode se establezca en Conditional.

Usar los controles UpdatePanel anidados

Los controles UpdatePanel se pueden anidar. Si se actualiza el panel primario, todos los paneles anidados también se actualizarán. Si se actualiza un panel secundarios, se actualiza sólo el panel secundario.

Configurar la actualización condicional Por defecto, los paneles actualizables en una página están sincronizados y se actualizan al mismo tiempo. Para hacer que cada panel se actualice independientemente de los otros, podemos cambiar el valor de la propiedad UpdateMode. EL valor por defecto es Always, lo que significa que el contenido del panel se actualiza en cada postback que se origina desde cualquier lugar en la página, desde dentro o fuera de la región actualizable.

AL cambiar el valor de la propiedad UpdateMode a Conditional, instruimos el panel actualizable para actualizar su contenido sólo si se ordena explícitamente que se actualice.

Page 13: Teoria Ajax y Aspnet

AJAX y ASP.NET

13 Esto incluye llamar al método Update, interceptar un postback desde un control hijo o cualquiera de los eventos declarados como desencadenadores.

Normalmente, cualquier control definido dentro de un control UpdatePanel actúa como un desencadenador implícito para el panel.

Podemos evitar que todos los controles hijo pasen a ser desencadenadores configurando el valor ChildrenAsTriggers como false. En este caso, un botón dentro del panel actualizable originaría, al hacer clic sobre él, un postback completo normal

Si sólo queremos que unos cuantos controles dentro de UpdatePanel actúen como desencadenadores, podemos definirlos como desencadenadores de un UpdatePanel concreto o podemos utilizar el método RegisterAsyncPostBackControl de la clase ScriptManager.

Este método nos permite registrar controles para realizar un postback asíncrono en vez de sçincrono.

ScriptManager1.RegisterAsyncPOstBackControl(Button1);

EL objeto control que pasamos como un argumento será un control no incluido en ningún panel actualizable y no es enumerable como un desencadenador. Los efectos en el postback que se originan desde el control son diferentes dependiendo del número de controles UpdatePanel de la página.

Si hay sólo un UpdatePanel en la página, el administrador de script puede deducir fácilmente cuál actualizar

Cuando existen paneles múltiples, para provocar la actualización tenemos que invocar explícitamente el método Update en el panel que queremos actualizar.

UpdatePanel1.Update();

Todos los controles localizados dentro del control UpdatePanel son pasados automáticamente como un argumento al método RegisterAsyncPostBackControl cuando ChildrenAsTriggers esté activada como true.

Uso de triggers Podemos asociar un control UpdatePanel con una enumeración de eventos del lado del servidor. Si un evento registrado es desencadenado por un postback el panel se actualiza. Los desencadenadores pueden definirse de manera declarativa o mediante programación. Añadimos un evento desencadenador de forma declarativa mediante la sección <Triggers> del control UpdatePanel.

Necesitamos especificar dos informaciones para cada desencadenador: la ID de control que se va a supervisar y el nombre del evento que se va a capturar. Resulta impresindible subrayar que el componente AsyncPostBackTrigger puede modificar tan solo eventos del lado del servidor. Por lo tanto, esto implica que el control debe tener AutoPostBack a true

Page 14: Teoria Ajax y Aspnet

AJAX y ASP.NET

14 En el ejemplo siguiente se muestra un marcado que define un control ScriptManager y un control UpdatePanel en una página. El control UpdatePanel contiene un control Button que actualiza el contenido del panel al hacer clic en él. De forma predeterminada, la propiedad ChildrenAsTriggers es true. Por consiguiente, el control Button actúa como un control de devolución de datos asincrónica.

<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void Button_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); } </script> <html> <head id="Head1" runat="server"> <title>UpdateProgress Example</title> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager" runat="server" /> <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server"> <ContentTemplate> <fieldset> <legend>UpdatePanel content</legend> <!-- Other content in the panel. --> <%=DateTime.Now.ToString() %> <br /> <asp:Button ID="Button1" Text="Refresh Panel" runat="server" /> </fieldset> </ContentTemplate> </asp:UpdatePanel> </form> </body> </html>

En el ejemplo siguiente se muestra cómo especificar un desencadenador para un control UpdatePanel.

<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void Button_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); } </script> <html>

Page 15: Teoria Ajax y Aspnet

AJAX y ASP.NET

15 <head id="Head1" runat="server"> <title>UpdateProgress Example</title> </head> <body> <form id="form1" runat="server"> <asp:Button ID="Button1" Text="Refresh Panel" runat="server" /> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server"> <Triggers> <asp:AsyncPostBackTrigger ControlID="Button1" /> </Triggers> <ContentTemplate> <fieldset> <legend>UpdatePanel content</legend> <%=DateTime.Now.ToString() %> </fieldset> </ContentTemplate> </asp:UpdatePanel> </form> </body> </html>

En el ejemplo siguiente se muestra el marcado para un control ScriptManager en la página maestra y un control UpdatePanel en una página de contenido. En este ejemplo, en la página maestra hay definida una propiedad denominada LastUpdate y se hace referencia a ella desde el control UpdatePanel.

<%@ Master Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> public DateTime LastUpdate { get { return (DateTime)(ViewState["LastUpdate"] ?? DateTime.Now); } set { ViewState["LastUpdate"] = value; } } protected void MasterButton2_Click(object sender, EventArgs e) { LastUpdate = DateTime.Now; ((UpdatePanel)ContentPlaceHolder1.FindControl("UpdatePanel1")).Update(); } protected void Page_Load(object sender, EventArgs e) {

Page 16: Teoria Ajax y Aspnet

AJAX y ASP.NET

16 ScriptManager1.RegisterAsyncPostBackControl(Button2); } </script> <html > <head id="Head1" runat="server"> <title>ScriptManager in Master Page Example</title> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <asp:Panel ID="MasterPanel1" runat="server" GroupingText="Master Page"> <asp:Button ID="Button1" runat="server" Text="Full Page Refresh" /> <asp:Button ID="Button2" runat="server" Text="Refresh Panel" OnClick="MasterButton2_Click" /> </asp:Panel> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder> </div> </form> </body> </html>

<%@ Page Language="C#" MasterPageFile="MasterCS.master" Title="ScriptManager in Content Page" %> <%@ MasterType VirtualPath="MasterCS.master" %> <script runat="server"> protected void Button3_Click(object sender, EventArgs e) { Master.LastUpdate = DateTime.Now; } </script> <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server"> <asp:Panel ID="Panel2" GroupingText="ContentPage" runat="server" > <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server"> <ContentTemplate> <p> Last updated: <strong> <%= Master.LastUpdate.ToString() %> </strong> </p> <asp:Button ID="Button3" Text="Refresh Panel" OnClick="Button3_Click"

Page 17: Teoria Ajax y Aspnet

AJAX y ASP.NET

17 runat="server" /> </ContentTemplate> </asp:UpdatePanel> </asp:Panel> </asp:Content>

El ejemplo siguiente muestra el marcado que define un control UpdatePanel dentro de otro control UpdatePanel. Un botón del panel primario desencadena una actualización del contenido tanto en el panel primario como secundario. El botón del panel secundario desencadena una actualización sólo del panel secundario.

<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> </script> <html > <head id="Head1" runat="server"> <title>UpdatePanelUpdateMode Example</title> <style type="text/css"> div.NestedPanel { position: relative; margin: 2% 5% 2% 5%; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager" runat="server" /> <asp:UpdatePanel ID="OuterPanel" UpdateMode="Conditional" runat="server"> <ContentTemplate> <div> <fieldset> <legend>Outer Panel </legend> <br /> <asp:Button ID="OPButton1" Text="Outer Panel Button" runat="server" /> <br /> Last updated on <%= DateTime.Now.ToString() %> <br /> <br /> <asp:UpdatePanel ID="NestedPanel1" UpdateMode="Conditional" runat="server"> <ContentTemplate> <div class="NestedPanel"> <fieldset> <legend>Nested Panel 1</legend> <br /> Last updated on <%= DateTime.Now.ToString() %> <br /> <asp:Button ID="NPButton1"

Page 18: Teoria Ajax y Aspnet

AJAX y ASP.NET

18 Text="Nested Panel 1 Button" runat="server" /> </fieldset> </div> </ContentTemplate> </asp:UpdatePanel> </fieldset> </div> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>

En el ejemplo siguiente se muestra un control UpdatePanel anidado con un control GridView. El control GridView está dentro de un control UpdatePanel, y cada fila de GridView contiene un control GridView anidado en otro control UpdatePanel.

<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html > <head id="Head1" runat="server"> <title>Browse Departments</title> <script runat="server"> protected void DepartmentsGridView_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { SqlDataSource s = (SqlDataSource)e.Row.FindControl("EmployeesDataSource"); System.Data.DataRowView r = (System.Data.DataRowView)e.Row.DataItem; s.SelectParameters["DepartmentID"].DefaultValue = r["DepartmentID"].ToString(); } } </script> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager runat="server" ID="ScriptManager1" EnablePartialRendering="true" /> <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:GridView ID="DepartmentsGridView" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" CellPadding="4" DataSourceID="DepartmentDataSource" ForeColor="#333333" GridLines="None" PageSize="3" OnRowDataBound="DepartmentsGridView_RowDataBound"> <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" /> <Columns> <asp:BoundField DataField="GroupName" HeaderText="Division" SortExpression="GroupName" > <ItemStyle Width="200px" /> </asp:BoundField>

Page 19: Teoria Ajax y Aspnet

AJAX y ASP.NET

19 <asp:BoundField DataField="Name" HeaderText="Department Name" SortExpression="Name" > <ItemStyle Width="160px" /> </asp:BoundField> <asp:TemplateField HeaderText="Employees"> <ItemTemplate> <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional"> <ContentTemplate> <asp:GridView ID="EmployeesGridView" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" CellPadding="3" DataSourceID="EmployeesDataSource" GridLines="Vertical" PageSize="4"> <FooterStyle BackColor="#CCCCCC" ForeColor="Black" /> <Columns> <asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpression="FirstName" > <ItemStyle Width="80px" /> </asp:BoundField> <asp:BoundField DataField="LastName" HeaderText="Last Name" SortExpression="LastName" > <ItemStyle Width="160px" /> </asp:BoundField> </Columns> <RowStyle BackColor="#EEEEEE" ForeColor="Black" /> <SelectedRowStyle BackColor="#008A8C" Font-Bold="True" ForeColor="White" /> <PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" /> <HeaderStyle BackColor="#000084" Font-Bold="True" ForeColor="White" /> <AlternatingRowStyle BackColor="Gainsboro" /> </asp:GridView> <asp:Label runat="server" ID="InnerTimeLabel"><%=DateTime.Now %></asp:Label> <asp:SqlDataSource ID="EmployeesDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT HumanResources.EmployeeDepartmentHistory.DepartmentID, HumanResources.vEmployee.EmployeeID, HumanResources.vEmployee.FirstName, HumanResources.vEmployee.LastName FROM HumanResources.EmployeeDepartmentHistory INNER JOIN HumanResources.vEmployee ON HumanResources.EmployeeDepartmentHistory.EmployeeID = HumanResources.vEmployee.EmployeeID WHERE HumanResources.EmployeeDepartmentHistory.DepartmentID = @DepartmentID ORDER BY HumanResources.vEmployee.LastName ASC, HumanResources.vEmployee.FirstName ASC"> <SelectParameters> <asp:Parameter Name="DepartmentID" DefaultValue="0" Type="int32" /> </SelectParameters>

Page 20: Teoria Ajax y Aspnet

AJAX y ASP.NET

20 </asp:SqlDataSource> </ContentTemplate> </asp:UpdatePanel> </ItemTemplate> <ItemStyle Height="170px" Width="260px" /> </asp:TemplateField> </Columns> <RowStyle BackColor="#F7F6F3" ForeColor="#333333" VerticalAlign="Top" /> <EditRowStyle BackColor="#999999" /> <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" /> <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" /> <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" HorizontalAlign="Left" /> <AlternatingRowStyle BackColor="White" ForeColor="#284775" VerticalAlign="Top" /> </asp:GridView> <asp:Label runat="server" ID="OuterTimeLabel"><%=DateTime.Now %></asp:Label> </ContentTemplate> </asp:UpdatePanel> &nbsp; <asp:SqlDataSource ID="DepartmentDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT DepartmentID, Name, GroupName FROM HumanResources.Department ORDER BY Name"> </asp:SqlDataSource> </div> </form> </body> </html>

En el ejemplo siguiente se muestra cómo actualizar un control UpdatePanel mediante programación. En este ejemplo, una página registra un control como desencadenador mediante una llamada al método RegisterAsyncPostBackControl. El código actualiza el control UpdatePanel mediante programación mediante una llamada al método Update.

<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected SortedList AnsweredQuestions { get { return (SortedList)(ViewState["AnsweredQuestions"] ?? new SortedList()); } set { ViewState["AnsweredQuestions"] = value; } } protected void Page_Load() { ScriptManager1.RegisterAsyncPostBackControl(SurveyDataList); } protected void ChoicesRadioButtonList_SelectedIndexChanged(object sender, EventArgs e) { SortedList answers = this.AnsweredQuestions; RadioButtonList r = (RadioButtonList)sender; answers[r.ToolTip] = r.SelectedValue;

Page 21: Teoria Ajax y Aspnet

AJAX y ASP.NET

21 this.AnsweredQuestions = answers; ResultsList.DataSource = this.AnsweredQuestions; ResultsList.DataBind(); if (this.AnsweredQuestions.Count == SurveyDataList.Items.Count) SubmitButton.Visible = true; UpdatePanel1.Update(); } protected void SubmitButton_Click(object sender, EventArgs e) { // Submit responses. } </script> <html > <head id="Head1" runat="server"> <title>Registering Controls as Async Postback Controls</title> <style type="text/css"> .AnswerFloatPanelStyle { background-color: bisque; position: absolute; right: 10px; height: 130px; width: 150px; border-right: silver thin solid; border-top: silver thin solid; border-left: silver thin solid; border-bottom: silver thin solid; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <div id="AnswerFloatPanel" class="AnswerFloatPanelStyle" runat="server"> <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server"> <ContentTemplate> Completed Questions: <asp:DataList ID="ResultsList" runat="server"> <ItemTemplate> <asp:Label ID="ResultQuestion" runat="server" Text='<%# Eval("Key") %>' /> :: <asp:Label ID="ResultAnswer" runat="server" Text='<%# Eval("Value") %>' /> </ItemTemplate> </asp:DataList> <p style="text-align: right"> <asp:Button ID="SubmitButton" Text="Submit" runat="server" Visible="false" OnClick="SubmitButton_Click" /> </p> <asp:Label ID="Message" runat="Server" /> </ContentTemplate> </asp:UpdatePanel> </div> <asp:XmlDataSource ID="SurveyDataSource" runat="server" XPath="/Questions/Question" DataFile="~/App_Data/SurveyQuestions.xml"/> <asp:DataList ID="SurveyDataList" DataSourceID="SurveyDataSource"

Page 22: Teoria Ajax y Aspnet

AJAX y ASP.NET

22 runat="server"> <ItemTemplate> <table cellpadding="2" cellspacing="2"> <tr> <td valign="top"> <asp:Label id="QuestionLabel" Text='<%# XPath("@Title")%>' runat="server" /> </td> </tr> <tr><td> <asp:RadioButtonList ID="ChoicesRadioButtonList" runat="server" DataSource='<%#XPathSelect("Choices/Choice") %>' DataTextField="InnerText" DataValueField="InnerText" AutoPostBack="True" ToolTip='<%# "Question" + XPath("@ID") %>' OnSelectedIndexChanged="ChoicesRadioButtonList_SelectedIndexChanged"/> </td></tr> </table> <hr /> </ItemTemplate> </asp:DataList> </div> </form> </body> </html>

<?xml version="1.0" encoding="UTF-8"?>

<!--Sample XML file, you should put it in App_Data folder -->

<Questions>

<Question Title="Favorite color?" ID="0">

<Choices>

<Choice>Red</Choice>

<Choice>Green</Choice>

<Choice>Blue</Choice>

</Choices>

</Question>

<Question Title="Favorite day or the week?" ID="1">

<Choices>

<Choice>Monday</Choice>

<Choice>Tuesday</Choice>

<Choice>Wednesday</Choice>

</Choices>

</Question>

<Question Title="Favorite activities?" ID="2">

<Choices>

<Choice>Gardening</Choice>

Page 23: Teoria Ajax y Aspnet

AJAX y ASP.NET

23 <Choice>Skiing</Choice>

<Choice>Walking</Choice>

</Choices>

</Question>

</Questions>

7.-El control UpdateProgress El control UpdateProgress proporciona información de estado acerca de las actualizaciones parciales de páginas en los controles UpdatePanel. Puede personalizar el contenido predeterminado y el diseño del control UpdateProgress. Para evitar que se produzcan intermitencias cuando una actualización parcial de páginas es muy rápida, puede especificar un retraso antes de que se muestre el control UpdateProgress.

El control UpdateProgress ayuda a diseñar una interfaz de usuario más intuitiva cuando una página web contiene uno o más controles UpdatePanel de representación parcial de páginas. Si una actualización parcial de páginas es lenta, puede usar el control UpdateProgress para proporcionar comentarios visuales acerca del estado de la actualización. Puede colocar varios controles UpdateProgress en una página, cada uno de ellos asociado con un control UpdatePanel distinto. Como alternativa, puede usar un control UpdateProgress y asociarlo con todos los controles UpdatePanel de la página.

El control UpdateProgress representa un elemento <div> que se muestra u oculta en función de que un control UpdatePanel asociado haya provocado o no una devolución asincrónica. El control UpdateProgress no aparece para la representación de la página inicial y las devoluciones sincrónicas.

Asociar un control UpdateProgress con un UpdatePanel

Para asociar un control UpdateProgress con un control UpdatePanel, debe establecer la propiedad AssociatedUpdatePanelID del control UpdateProgress. Cuando se origina un evento de devolución desde un control UpdatePanel, se muestran los controles UpdateProgress asociados. Si no se asocia el control UpdateProgress con un control UpdatePanel específico, el control UpdateProgress muestra el progreso de las devoluciones asincrónicas.

Si la propiedad ChildrenAsTriggers de un control UpdatePanel se establece en false y se origina una devolución asincrónica desde dicho control UpdatePanel, se mostrarán todos los controles UpdateProgress asociados.

Crear contenido para el UpdateProgress

Para especificar el mensaje que muestra un control UpdateProgress, coloque el contenido que desee en el panel de la vista Diseño. Por ejemplo, puede arrastrar otros controles ASP.NET y HTML al panel y, a continuación, colocar el cursor en el panel y escribir directamente en él. Al agregar un mensaje a un control UpdateProgress en la vista Diseño, se agregan

Page 24: Teoria Ajax y Aspnet

AJAX y ASP.NET

24 automáticamente las etiquetas <ProgressTemplate> necesarias alrededor del contenido. Si agrega contenido a un control UpdateProgress en la vista Código en lugar de hacerlo en la vista Diseño, debe agregar manualmente las etiquetas <ProgressTemplate></ProgressTemplate> si aún no existen; de lo contrario, el mensaje no se representará.

Especificar el diseño de contenido

Si la propiedad DynamicLayout es true, el control UpdateProgress no ocupa espacio inicialmente en la presentación de la página. En su lugar, la página cambia dinámicamente para mostrar el contenido del control UpdateProgress cuando es necesario. Para admitir la presentación dinámica, el control se representa como un elemento <div> cuya propiedad de estilo de presentación se ha establecido inicialmente en none.

Si la propiedad DynamicLayout es false, el control UpdateProgress ocupa espacio en la presentación de la página, aunque no sea visible. En tal caso, el elemento <div> del control tiene la propiedad de estilo de presentación establecida en block y la visibilidad establecida inicialmente en hidden.

Colocar controles UpdateProgress en la página

Los controles UpdateProgress pueden colocarse dentro o fuera de los controles UpdatePanel. Un control UpdateProgress aparece cuando el control UpdatePanel con el que está asociado se actualiza como resultado de una devolución asincrónica. Esto se cumple aunque el control UpdateProgress se encuentre dentro de otro control UpdatePanel.

Si un control UpdatePanel se encuentra dentro de otro panel de actualización, una devolución originada dentro del panel secundario hace que se muestren los controles UpdateProgress asociados con el panel secundario. También se muestran los controles UpdateProgress asociados con el panel primario. Si se origina una devolución desde un control secundario inmediato del panel primario, sólo se muestran los controles UpdateProgress asociados con el panel primario. Esto sigue la lógica del desencadenamiento de devoluciones.

<asp:UpdateProgress ID="UpdateProgress1" runat="server"> <ProgressTemplate> An update is in progress... </ProgressTemplate> </asp:UpdateProgress>

En el ejemplo siguiente se muestra un control UpdateProgress que muestra el estado de actualización de dos controles UpdatePanel.

<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void Button_Click(object sender, EventArgs e) { System.Threading.Thread.Sleep(3000); } </script>

Page 25: Teoria Ajax y Aspnet

AJAX y ASP.NET

25 <html > <head id="Head1" runat="server"> <title>UpdateProgress Example</title> <style type="text/css"> #UpdatePanel1, #UpdatePanel2, #UpdateProgress1 { border-right: gray 1px solid; border-top: gray 1px solid; border-left: gray 1px solid; border-bottom: gray 1px solid; } #UpdatePanel1, #UpdatePanel2 { width:200px; height:200px; position: relative; float: left; margin-left: 10px; margin-top: 10px; } #UpdateProgress1 { width: 400px; background-color: #FFC080; bottom: 0%; left: 0px; position: absolute; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server"> <ContentTemplate> <%=DateTime.Now.ToString() %> <br /> <asp:Button ID="Button1" runat="server" Text="Refresh Panel" OnClick="Button_Click" /> </ContentTemplate> </asp:UpdatePanel> <asp:UpdatePanel ID="UpdatePanel2" UpdateMode="Conditional" runat="server"> <ContentTemplate> <%=DateTime.Now.ToString() %> <br /> <asp:Button ID="Button2" runat="server" Text="Refresh Panel" OnClick="Button_Click"/> </ContentTemplate> </asp:UpdatePanel> <asp:UpdateProgress ID="UpdateProgress1" runat="server"> <ProgressTemplate> Update in progress... </ProgressTemplate> </asp:UpdateProgress> </div> </form> </body> </html>

En el ejemplo siguiente se muestran dos controles UpdateProgress. Cada control muestra el estado de actualización de un control UpdatePanel asociado.

<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void Button_Click(object sender, EventArgs e)

Page 26: Teoria Ajax y Aspnet

AJAX y ASP.NET

26 { System.Threading.Thread.Sleep(3000); } </script> <html > <head id="Head1" runat="server"> <title>UpdateProgress Example</title> <style type="text/css"> #UpdatePanel1, #UpdatePanel2 { width:200px; height:200px; position: relative; float: left; margin-left: 10px; margin-top: 10px; border-right: gray 1px solid; border-top: gray 1px solid; border-left: gray 1px solid; border-bottom: gray 1px solid; } #UpdateProgress1, #UpdateProgress2 { width: 200px; background-color: #FFC080; position: absolute; bottom: 0px; left: 0px; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server"> <ContentTemplate> <%=DateTime.Now.ToString() %> <br /> <asp:Button ID="Button1" runat="server" Text="Refresh Panel" OnClick="Button_Click" /> <asp:UpdateProgress ID="UpdateProgress1" AssociatedUpdatePanelID="UpdatePanel1" runat="server"> <ProgressTemplate> UpdatePanel1 updating... </ProgressTemplate> </asp:UpdateProgress> </ContentTemplate> </asp:UpdatePanel> <asp:UpdatePanel ID="UpdatePanel2" UpdateMode="Conditional" runat="server"> <ContentTemplate> <%=DateTime.Now.ToString() %> <br /> <asp:Button ID="Button2" runat="server" Text="Refresh Panel" OnClick="Button_Click"/> <asp:UpdateProgress ID="UpdateProgress2" AssociatedUpdatePanelID="UpdatePanel2" runat="server"> <ProgressTemplate> UpdatePanel2 updating... </ProgressTemplate> </asp:UpdateProgress> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>

Especificar el diseño del contenido

Page 27: Teoria Ajax y Aspnet

AJAX y ASP.NET

27 Si la propiedad DynamicLayout es true, el control UpdateProgress no ocupa espacio inicialmente en la presentación de la página. En su lugar, la página cambia dinámicamente para mostrar el contenido del control UpdateProgress cuando es necesario. Para admitir la presentación dinámica, el control se representa como un elemento <div> cuya propiedad de estilo de presentación se ha establecido inicialmente en none.

Si la propiedad DynamicLayout es false, el control UpdateProgress ocupa espacio en la presentación de la página, aunque no sea visible. En tal caso, el elemento <div> del control tiene la propiedad de estilo de presentación establecida en block y la visibilidad establecida inicialmente en hidden.

Incluir controles UpdateProgress en la página

Puede colocar los controles UpdateProgress dentro o fuera de los controles UpdatePanel. Un control UpdateProgress se muestra siempre que el control UpdatePanel al que está asociado se actualiza como resultado de una devolución de datos asincrónica. Esto es así incluso si el control UpdateProgress está dentro de otro control UpdatePanel.

Si un control UpdatePanel está dentro de otro panel de actualización, una devolución de datos que se origina dentro del panel secundario genera la presentación de cualquier control UpdateProgress asociado al panel secundario. También muestra cualquier control UpdateProgress asociado al panel primario. Si una devolución de datos se origina desde un control secundario inmediato del panel primario, sólo se muestran los controles UpdateProgress asociados al panel primario. Este proceso sigue la lógica de la forma de desencadenamiento de las devoluciones de datos.

8.- Timer Es el homólogo del servidor de un cliente creado utilizando el método Window.set.Timeout. EL control Timer provoca un postback según lo especificado en la propiedad Interval. El postback desencadena un evento Tick. Utilizando el temporizador como un desencadenador de un panel actualizable, podemos actualizar el contenido del panel periódicamente.

El control Timer de ASP.NET AJAX realiza devoluciones de datos a intervalos definidos. Si se usa el control Timer con un control UpdatePanel, se pueden habilitar actualizaciones parciales de páginas a un intervalo definido. El control Timer también permite enviar la página completa.

El control Timer se usa para realizar las siguientes acciones:

• Actualizar periódicamente el contenido de uno o más controles UpdatePanel sin actualizar toda la página web.

• Ejecutar código en el servidor cada vez que un control Timer provoque una devolución de datos.

• Enviar de forma sincrónica la página web completa al servidor web a intervalos definidos.

Page 28: Teoria Ajax y Aspnet

AJAX y ASP.NET

28

El control Timer es un control de servidor que incrusta un componente JavaScript en la página web. El componente JavaScript inicia la devolución de datos desde el explorador cuando ha transcurrido el intervalo definido en la propiedad Interval. Las propiedades para el control Timer se definen en el código que se ejecuta en el servidor y se pasan al componente JavaScript.

Cuando se usa el control Timer, se debe incluir una instancia de la clase ScriptManager en la página web.

Cuando el control Timer inicia una devolución de datos, se genera el evento Tick en el servidor. Se puede crear un controlador de eventos para el evento Tick de forma que realice acciones cuando la página se envíe al servidor.

La propiedad Interval se usa para especificar la frecuencia con la que se producirán las devoluciones y la propiedad Enabled para activar o desactivar el control Timer. La propiedad Interval se define en milisegundos y tiene un valor predeterminado de 60.000 milisegundos (60 segundos).

Si se establece la propiedad Interval de un control Timer en un valor pequeño, se puede generar un tráfico considerable hacia el servidor web. El control Timer se usa para actualizar el contenido únicamente con la frecuencia que sea necesaria.

Se puede incluir más de un control Timer en una página web cuando hay que actualizar distintos controles UpdatePanel a intervalos diferentes. Como alternativa, una única instancia del control Timer puede ser el desencadenador de más de un control UpdatePanel en una página web.

Uso del Timer en un control UpdatePanel

Cuando el control Timer se incluye dentro de un control UpdatePanel, el control Timer funciona automáticamente como desencadenador para el control UpdatePanel. Este comportamiento se puede invalidar si la propiedad ChildrenAsTriggers del control UpdatePanel se establece en False.

Para los controles Timer que se encuentran dentro de un control UpdatePanel, el componente de temporización JavaScript se vuelve a crear sólo cuando finaliza cada devolución de datos. Por lo tanto, el intervalo de tiempo no se inicia hasta que la página vuelve de la devolución de datos. Por ejemplo, si la propiedad Interval se establece en 60.000 milisegundos (60 segundos) pero la devolución de datos tarda 3 segundos en realizarse, la siguiente devolución de datos se producirá 63 segundos después la anterior.

Uso del Timer fuera de un UpdatePanel

Cuando el control Timer está fuera de un control UpdatePanel, debe definirse explícitamente el control Timer como un desencadenador para que el control UpdatePanel se actualice.

Page 29: Teoria Ajax y Aspnet

AJAX y ASP.NET

29 Si el control Timer está fuera de un control UpdatePanel, el componente de temporización JavaScript seguirá ejecutándose mientras se procesa la devolución de datos. Por ejemplo, si la propiedad Interval se establece en 60.000 milisegundos (60 segundos) y la devolución de datos tarda 3 segundos en realizarse, la siguiente devolución de datos se producirá 60 segundos después la anterior. El usuario verá el contenido actualizado en el control UpdatePanel sólo durante 57 segundos.

La propiedad Interval debe establecerse en un valor que permita que una devolución de datos asincrónica se complete antes de que se inicie la siguiente devolución de datos. Si se inicia una nueva devolución de datos mientras se está procesando una devolución de datos anterior, se cancelará la primera devolución de datos.

En el ejemplo de código siguiente se muestra cómo incluir un control Timer dentro de un control UpdatePanel.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %> <!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 runat="server"> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager runat="server" ID="ScriptManager1" /> <asp:UpdatePanel runat="server" ID="UpdatePanel1" UpdateMode="Conditional"> <ContentTemplate> <asp:Timer ID="Timer1" runat="server" Interval="120000" OnTick="Timer1_Tick"> </asp:Timer> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>

En el ejemplo siguiente se muestra cómo usar el control Timer fuera de un control UpdatePanel.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %> <!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 runat="server"> <title></title> </head> <body> <form id="form1" runat="server">

Page 30: Teoria Ajax y Aspnet

AJAX y ASP.NET

30 <div> <asp:ScriptManager runat="server" ID="ScriptManager1" /> <asp:Timer ID="Timer1" runat="server" Interval="120000" OnTick="Timer1_Tick"> </asp:Timer> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <Triggers> <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" /> </Triggers> <ContentTemplate> <asp:Label ID="Label1" runat="server"></asp:Label> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>

En el ejemplo siguiente se muestra un control UpdatePanel que muestra el precio generado aleatoriamente de una acción y el momento en el que se generó. De forma predeterminada, el control Timer actualiza el contenido del control UpdatePanel cada 10 segundos. El usuario puede decidir actualizar el precio de las acciones cada 10 segundos, cada 60 segundos o no actualizarlo nunca. Cuando el usuario decide no actualizar el precio de las acciones, la propiedad Enabled se establece en false.

<%@ Page Language="C#" AutoEventWireup="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html > <head id="Head1" runat="server"> <title>Timer Example Page</title> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { OriginalTime.Text = DateTime.Now.ToLongTimeString(); } protected void Timer1_Tick(object sender, EventArgs e) { StockPrice.Text = GetStockPrice(); TimeOfPrice.Text = DateTime.Now.ToLongTimeString(); } private string GetStockPrice() { double randomStockPrice = 50 + new Random().NextDouble(); return randomStockPrice.ToString("C"); } protected void RadioButton1_CheckedChanged(object sender, EventArgs e) { Timer1.Enabled = true; Timer1.Interval = 10000; }

Page 31: Teoria Ajax y Aspnet

AJAX y ASP.NET

31 protected void RadioButton2_CheckedChanged(object sender, EventArgs e) { Timer1.Enabled = true; Timer1.Interval = 60000; } protected void RadioButton3_CheckedChanged(object sender, EventArgs e) { Timer1.Enabled = false; } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server" /> <asp:Timer ID="Timer1" OnTick="Timer1_Tick" runat="server" Interval="10000" /> <asp:UpdatePanel ID="StockPricePanel" runat="server" UpdateMode="Conditional"> <Triggers> <asp:AsyncPostBackTrigger ControlID="Timer1" /> </Triggers> <ContentTemplate> Stock price is <asp:Label id="StockPrice" runat="server"></asp:Label><BR /> as of <asp:Label id="TimeOfPrice" runat="server"></asp:Label> <br /> </ContentTemplate> </asp:UpdatePanel> <div> <br /> Update stock price every:<br /> <asp:RadioButton ID="RadioButton1" AutoPostBack="true" GroupName="TimerFrequency" runat="server" Text="10 seconds" OnCheckedChanged="RadioButton1_CheckedChanged" /><br /> <asp:RadioButton ID="RadioButton2" AutoPostBack="true" GroupName="TimerFrequency" runat="server" Text="60 seconds" OnCheckedChanged="RadioButton2_CheckedChanged" /><br /> <asp:RadioButton ID="RadioButton3" AutoPostBack="true" GroupName="TimerFrequency" runat="server" Text="Never" OnCheckedChanged="RadioButton3_CheckedChanged" /> <br /> Page loaded at <asp:Label ID="OriginalTime" runat="server"></asp:Label> </div> </form> </body> </html>

Page 32: Teoria Ajax y Aspnet

AJAX y ASP.NET

32 Crear Script de Cliente con la librería de AJAX del lado del cliente

1.- Arquitectura de las características de AJAX en ASP.NET La arquitectura de las características de AJAX en ASP.NET está compuesta de dos partes: bibliotecas de scripts de cliente y componentes de servidor. Estas partes se integran para proporcionar un marco de desarrollo sólido.

Arquitectura de cliente y servidor de AJAX en ASP.NET

La ilustración muestra la funcionalidad de la Microsoft AJAX Library basada en cliente, incluidas la posibilidad de crear componentes de cliente, compatibilidad de exploradores, conexión de red y servicios principales. La ilustración también muestra la funcionalidad de las características de AJAX basadas en servidor, incluidos la compatibilidad para scripts, servicios web, servicios de aplicación y controles de servidor.

2.- Crear Scripts de Cliente Tres formas de definir scripts de cliente:

• Definir un bloque de script en la página web. • Usar la clase ClientScriptManager para añadir dinámicamente javaScript a la página • Utilizar el control de servidor ScriptManager para registrar JavaScript en la página web.

Page 33: Teoria Ajax y Aspnet

AJAX y ASP.NET

33 2.1.- Añadir bloque de código a la página ASP.NET Podemos añadir bloque de código en la página ASP.NET o referenciar a un archivo .js

Es el método tradicional de trabajo con JavaScript en una página web.

<%@ Page Language="C#" AutoEventWireup="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html> <head id="Head1" runat="server"> <title>Script Block</title> <script language="javascript" type="text/javascript"> function Collapse() { if (DivCollapse.style.display == "") { DivCollapse.style.display = "none"; document.forms[0].ButtonCollapse.value = "Open"; } else { DivCollapse.style.display = ""; document.forms[0].ButtonCollapse.value = "Close"; } } </script> </head> <body style="font-family: Verdana;"> <form id="form1" runat="server"> <div> <div style="width: 200px; background-color: Blue; color: White; border-style: solid; border-width: thin; border-color: Blue"> <div style="float: left; vertical-align: middle; margin-top: 3px;"> Element Title </div> <div style="float: right; vertical-align: middle"> <input id="ButtonCollapse" type="button" value="Close" onclick="Collapse()" /> </div> </div> <div id="DivCollapse" style="width: 200px; height: 200px; border-style: solid; border-width: thin; border-color: Blue"> <div style="margin-top: 20px; text-align: center;"> Content area ... </div> </div> </div> </form> </body> </html>

En el ejemplo anterior el código javaScript está colocado dentro de la página, otra posibilidad sería colocar el código JS en un archivo y realizar el enlace

<script type="text/javascript" src="SiteScripts.js"></script>

Page 34: Teoria Ajax y Aspnet

AJAX y ASP.NET

34 EN el próximo ejemplo vemos como podemos especificar para que un control de ASP.NET pueda llamar a una función javaScript.

<%@ Page Language="C#" AutoEventWireup="true" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <script runat="server"> protected void ButtonCollapse_Click(object sender, EventArgs e) { } </script> <html> <head id="Head1" runat="server"> <title>Script Block</title> <script language="javascript" type="text/javascript"> function Collapse() { if (DivCollapse.style.display == "") { DivCollapse.style.display = "none"; document.forms[0].ButtonCollapse.value = "Open"; } else { DivCollapse.style.display = ""; document.forms[0].ButtonCollapse.value = "Close"; } } </script> </head> <body style="font-family: Verdana;"> <form id="form1" runat="server"> <div> <div style="width: 200px; background-color: Blue; color: White; border-style: solid; border-width: thin; border-color: Blue"> <div style="float: left; vertical-align: middle; margin-top: 3px;"> Element Title </div> <div style="float: right; vertical-align: middle"> <asp:button id="ButtonCollapse" runat="server" text="Close" onClientClick="Collapse()" /> </div> </div> <div id="DivCollapse" style="width: 200px; height: 200px; border-style: solid; border-width: thin; border-color: Blue"> <div style="margin-top: 20px; text-align: center;"> Content area ... </div> </div> </div>

Page 35: Teoria Ajax y Aspnet

AJAX y ASP.NET

35 </form> </body> </html>

Tambien podemos utilizar la propiedad ClientId para cambiar el ID en el cliente.

2.2.- Añadir Script dinámicamente a ASP.NET Hay veces que necesitaremos generar código JavaScript y añadirlo dinámicamente a la página en tiempo de ejecución.

Para ello utilizaremos la clase ClientScriptManager y de esta forma registrar dinámicamente JavaScript.

Una instancia de la clase ClientScriptManager se expone a través de la propiedad ClientScript del objeto Page.

Usaremos esta propiedad para añadir JavaScript a la página en tiempo de ejecución, determinar si un script ya ha sido registrado, y otras tareas relacionadas.

Para añadir un script, definimos el bloque de código o el archivo con el código. Y llamamos al método RegisterClientScriptBlock del objeto ClientScriptManager.

public void RegisterClientScriptBlock ( Type type, string key, string script, bool addScriptTags )

type Tipo de la secuencia de comandos de cliente que se va a registrar.

key Clave de la secuencia de comandos de cliente que se va a registrar.

script Literal de la secuencia de comandos de cliente que se va a registrar.

addScriptTags Valor booleano que indica si se agregan etiquetas de secuencia de comandos.

Una secuencia de comandos de cliente se identifica de forma única mediante su clave y su tipo. Las secuencias de comandos de la misma clave y tipo se consideran duplicadas. Sólo se puede registrar una secuencia de comandos con un par de clave y tipo específicos con la página. Al intentar registrar una secuencia de comandos ya registrada no se crea un duplicado de ella.

Llame al método IsStartupScriptRegistered para determinar si ya se encuentra registrada una secuencia de comandos de inicio con par de clave y tipo específicos y evitar innecesariamente agregar la secuencia de comandos.

En esta sobrecarga del método RegisterClientScriptBlock, puede indicar si la secuencia de comandos proporcionada en el parámetro script se ajusta con un bloque de elemento <script>

Page 36: Teoria Ajax y Aspnet

AJAX y ASP.NET

36 mediante el parámetro addScriptTags. El establecimiento del parámetro addScriptTags a true indica que automáticamente se agregarán etiquetas de secuencia de comandos.

2.2.1.- RegisterClientScriptBlock El método RegisterClientScriptBlock agrega un bloque de secuencia de comandos a la parte superior de la página representada. No se garantiza que los bloques de secuencias de comandos envíen los resultados en el orden en que están registrados

<%@ Page Language="C#"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> public void Page_Load(Object sender, EventArgs e) { // Define the name and type of the client scripts on the page. String csname1 = "PopupScript"; String csname2 = "ButtonClickScript"; Type cstype = this.GetType(); // Get a ClientScriptManager reference from the Page class. ClientScriptManager cs = Page.ClientScript; // Check to see if the startup script is already registered. if (!cs.IsStartupScriptRegistered(cstype, csname1)) { String cstext1 = "alert('Hello World');"; cs.RegisterStartupScript(cstype, csname1, cstext1, true); } // Check to see if the client script is already registered. if (!cs.IsClientScriptBlockRegistered(cstype, csname2)) { StringBuilder cstext2 = new StringBuilder(); cstext2.Append("<script type=\"text/javascript\"> function DoClick() {"); cstext2.Append("Form1.Message.value='Text from client script.'} </"); cstext2.Append("script>"); cs.RegisterClientScriptBlock(cstype, csname2, cstext2.ToString(), false); } } </script> <html > <head> <title>ClientScriptManager Example</title> </head> <body> <form id="Form1" runat="server"> <input type="text" id="Message" /> <input type="button" value="ClickMe" onclick="DoClick()" /> </form> </body> </html>

Page 37: Teoria Ajax y Aspnet

AJAX y ASP.NET

37 2.2.2.- RegisterClientInclude

public void RegisterClientScriptInclude( Type type, string key, string url ) Registra la inclusión de la secuencia de comandos de cliente con el objeto Page utilizando un tipo, una clave y una dirección URL. Esta sobrecarga del método RegisterClientScriptInclude acepta los parámetros key y url para identificar la secuencia de comandos, así como un parámetro type para especificar la identificación de la inclusión de la secuencia de comandos de cliente. Especifique el tipo basándose en el objeto que tendrá acceso al recurso. Por ejemplo, cuando se utiliza una instancia de Page para obtener acceso al recurso, se ha de especificar el tipo Page. En el ejemplo de código siguiente se muestra el uso del método RegisterClientScriptInclude. Tenga en cuenta que, aunque se quite la lógica para comprobar la inclusión de secuencias de comandos de cliente existentes, no habrá secuencias de comandos de cliente duplicadas en la página representada, porque el método RegisterClientScriptInclude comprueba los duplicados. La ventaja de la comprobación es reducir los cálculos innecesarios. <%@ Page Language="C#"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> public void Page_Load(Object sender, EventArgs e) { // Define the name, type and url of the client script on the page. String csname = "ButtonClickScript"; String csurl = "~/script_include.js"; Type cstype = this.GetType(); // Get a ClientScriptManager reference from the Page class. ClientScriptManager cs = Page.ClientScript; // Check to see if the include script exists already. if (!cs.IsClientScriptIncludeRegistered(cstype, csname)) { cs.RegisterClientScriptInclude(cstype, csname, ResolveClientUrl(csurl)); } } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>ClientScriptManager Example</title> </head> <body> <form id="Form1" runat="server"> <div>

Page 38: Teoria Ajax y Aspnet

AJAX y ASP.NET

38 <input type="text" id="Message"/> <input type="button" value="ClickMe" onclick="DoClick()"/> </div> </form> </body> </html>

Este ejemplo necesita un javascript llamado script_include.js con el siguiente código:

function DoClick() { Form1.Message.value = 'Text from include script.' }

2.2.3.- RegisterStartupScript Registra la secuencia de comandos de inicio con el objeto Page utilizando un tipo, una clave, un literal de secuencia de comandos y un valor booleano que indican si se agregan etiquetas de secuencia de comandos.

public void RegisterStartupScript( Type type, string key, string script, bool addScriptTags )

type

Tipo: System.Type

Tipo de la secuencia de comandos de inicio que se va a registrar.

key

Tipo: System.String

Clave de la secuencia de comandos de inicio que se va a registrar.

script

Tipo: System.String

Literal de la secuencia de comandos de inicio que se va a registrar.

addScriptTags

Tipo: System.Boolean

Valor booleano que indica si se agregan etiquetas de secuencia de comandos.

Page 39: Teoria Ajax y Aspnet

AJAX y ASP.NET

39 Una secuencia de comandos de inicio se identifica de forma única mediante su clave y su tipo. Las secuencias de comandos de la misma clave y tipo se consideran duplicadas. Sólo se puede registrar una secuencia de comandos con un par de clave y tipo específicos con la página. Al intentar registrar una secuencia de comandos ya registrada no se crea un duplicado de ella.

Llame al método IsStartupScriptRegistered para determinar si ya se encuentra registrada una secuencia de comandos de inicio con par de clave y tipo específicos y evitar innecesariamente agregar la secuencia de comandos.

En esta sobrecarga del método RegisterStartupScript, puede indicar si la secuencia de comandos proporcionada en el parámetro script se ajusta con un bloque de elemento <script> mediante el parámetro addScriptTags. El establecimiento del parámetro addScriptTags a true indica que automáticamente se agregarán etiquetas de secuencia de comandos.

El bloque de secuencia de comandos agregado por el método RegisterStartupScript se ejecuta cuando la página termina de cargar pero antes de que se provoque el evento OnLoad de la página. No se garantiza que los bloques de secuencias de comandos envíen los resultados en el orden en que están registrados. Si el orden de los bloques de secuencias de comandos es importante, utilice un objeto StringBuilder para reunir las secuencias de comandos en una sola cadena y registrarlas después en un solo bloque de secuencias de comandos de cliente.

En el ejemplo de código siguiente se muestra el uso del método RegisterStartupScript. Observe que el parámetro addScriptTags se establece en false por lo que las etiquetas de secuencia de comandos de apertura y cierra se incluyen con el parámetro script.

<%@ Page Language="C#"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> public void Page_Load(Object sender, EventArgs e) { // Define the name and type of the client scripts on the page. String csname1 = "PopupScript"; String csname2 = "ButtonClickScript"; Type cstype = this.GetType(); // Get a ClientScriptManager reference from the Page class. ClientScriptManager cs = Page.ClientScript; // Check to see if the startup script is already registered. if (!cs.IsStartupScriptRegistered(cstype, csname1)) { String cstext1 = "alert('Hello World');"; cs.RegisterStartupScript(cstype, csname1, cstext1, true); } // Check to see if the client script is already registered. if (!cs.IsClientScriptBlockRegistered(cstype, csname2)) { StringBuilder cstext2 = new StringBuilder(); cstext2.Append("<script type=\"text/javascript\"> function DoClick() {"); cstext2.Append("Form1.Message.value='Text from client script.'} </"); cstext2.Append("script>");

Page 40: Teoria Ajax y Aspnet

AJAX y ASP.NET

40 cs.RegisterClientScriptBlock(cstype, csname2, cstext2.ToString(), false); } } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>ClientScriptManager Example</title> </head> <body> <form id="Form1" runat="server"> <input type="text" id="Message" /> <input type="button" value="ClickMe" onclick="DoClick()" /> </form> </body> </html>

2.2.4.- RegisterOnSubmitStatement Registra una instrucción OnSubmit con el objeto Page utilizando un tipo, una clave y un literal de secuencia de comandos. La instrucción se ejecuta cuando se envía el objeto HtmlForm.

public void RegisterOnSubmitStatement( Type type, string key, string script )

type

Tipo: System.Type

Tipo de la instrucción OnSubmit que se va a registrar.

key

Tipo: System.String

Clave de la instrucción OnSubmit que se va a registrar.

script

Tipo: System.String

Literal de secuencia de comandos de la instrucción OnSubmit que se va a registrar.

Una instrucción OnSubmit se identifica de forma única mediante su clave y su tipo. Las instrucciones de la misma clave y tipo se consideran duplicadas. Sólo se puede registrar una instrucción con un par de clave y tipo específicos con la página. Al intentar registrar una instrucción que ya está registrada no se creará un duplicado de ella.

Llame al método IsOnSubmitStatementRegistered para determinar si una instrucción OnSubmit ya está registrada con un par de clave y tipo específicos y evitar innecesariamente agregar la secuencia de comandos.

Page 41: Teoria Ajax y Aspnet

AJAX y ASP.NET

41 El parámetro script del método RegisterOnSubmitStatement puede contener varios comandos de secuencia de comandos siempre y cuando se delimiten correctamente con un punto y coma (;).

El método RegisterOnSubmitStatement agrega una secuencia de comandos que se ejecuta antes de enviar la página y le da una oportunidad de cancelar el envío.

En el ejemplo de código siguiente se muestra el uso del método RegisterOnSubmitStatement.

2.3.- Utilizar el control de servidor ScriptManager para registrar JavaScript en la página web En la mayoría de los escenarios, la manera más fácil de agregar un archivo de script a una página ASP.NET es con marcado, como en el ejemplo siguiente:

<asp:ScriptManager ID="SMgr" runat="server"> <Scripts> <asp:ScriptReference Path="./Script.js" /> </Scripts> </asp:ScriptManager>

Sin embargo, también es posible agregar dinámicamente referencias de script. Los desarrolladores de páginas pueden hacer esto para tener más control sobre cómo se agrega un script. Por ejemplo, podrían agregar scripts dinámicamente para ayudar a conservar los recursos de memoria, no cargando una biblioteca de scripts grande a menos que sea necesario. O bien, podrían cargar versiones de scripts diferentes para tipos de usuarios diferentes. Los desarrolladores de controles agregan scripts dinámicamente al crear controles de script o controles extensores para dejar disponibles los recursos del script automáticamente para la página que hospeda el control.

Las referencias de script pueden especificar archivos de script o scripts incrustados como recursos en ensamblados. Los scripts se pueden encontrar en las versiones de depuración y comerciales. El siguiente procedimiento muestra cómo asignar una referencia de script a una página en cada una de estas situaciones.

Todos los archivos de script que se van a registrar con el control ScriptManager deben llamar al método notifyScriptLoaded para notificar a la aplicación que el script ha terminado de cargarse.

2.3.1.- Agregar dinámicamente una referencia de script a una página 1. 1.- Si no conoce el identificador del elemento <asp:ScriptManager> de la página, llame

al método ScriptManagerGetCurrent() del control ScriptManager para obtener la instancia actual del control. Compruebe null en caso de que no haya ningún control ScriptManager en la página. Si sabe que hay un elemento <asp:ScriptManager> en la página y conoce su valor ID, puede omitir este paso.

El ejemplo siguiente muestra cómo comprobar la existencia de un control ScriptManager en una página y, a continuación, obtiene la instancia actual o crea una nueva.

Page 42: Teoria Ajax y Aspnet

AJAX y ASP.NET

42 // If there is a ScriptManager on the page, use it. // If not, throw an exception. ScriptManager Smgr = ScriptManager.GetCurrent(Page); if (Smgr == null) throw new Exception("ScriptManager not found.");

2.- Crear un objeto ScriptReference.

ScriptReference SRef = new ScriptReference();

3.- Para los scripts basados en archivos, si sabe que la propiedad ScriptPath del control ScriptManager está establecida en la ubicación correcta para el archivo de script, establezca la propiedad Name de la instancia ScriptReference en el nombre del archivo de script. En caso contrario, establezca la propiedad Path del objeto ScriptReference en la dirección URL absoluta, relativa o relativa a la aplicación del archivo de script que desea agregar.

// If you know that Smgr.ScriptPath is correct... SRef.Name = "Script.js"; // Or, to specify an app-relative path... SRef.Path = "~/Scripts/Script.js";

4.- Agregue el objeto ScriptReference a la colección Scripts del control ScriptManager. Smgr.Scripts.Add(SRef);

3.- Implementar mediante programación devoluciones de llamada de cliente sin devoluciones de datos en páginas web de ASP.NET En el modelo predeterminado para las páginas Web ASP.NET, el usuario interactúa con una página y hace clic en un botón o realiza alguna otra acción que da como resultado una devolución de datos. La página y sus controles se vuelven a crear, se ejecuta el código de la página en el servidor y se representa una nueva versión de la página en el explorador. Sin embargo, en algunas situaciones, es útil ejecutar código del servidor desde el cliente sin realizar una devolución de datos. Si la secuencia de comandos de cliente de la página incluye información de estado (por ejemplo, valores de variables locales), enviar la página y obtener una nueva copia ocasiona la destrucción de dicho estado. Además, las devoluciones de datos de página introducen una sobrecarga de procesamiento que puede disminuir el rendimiento y obligar al usuario a esperar a que la página se procese y se vuelva a crear.

Para evitar la pérdida del estado del cliente y no incurrir en la sobrecarga de procesamiento que supone enviar los datos al servidor y esperar a que los devuelva tras procesarlos, puede agregar código a una página Web ASP.NET para que pueda realizar devoluciones de llamada del cliente. En una devolución de llamada del cliente, una función de secuencia de comandos de cliente envía una solicitud a una página Web ASP.NET. La página Web ejecuta una versión modificada de su ciclo de vida normal (se inicia la página y se crean sus controles y otros miembros) y, a continuación, se invoca un método marcado de forma especial. Dicho método realiza el procesamiento especificado en el código y, a continuación, devuelve al explorador un

Page 43: Teoria Ajax y Aspnet

AJAX y ASP.NET

43 valor que otra función de secuencia de comandos de cliente puede leer. A lo largo de este proceso, la página está activa en el explorador.

3.1.- Componentes de las devoluciones de llamada del cliente La creación de una página ASP.NET que implemente devoluciones de llamada del cliente es una operación similar a la creación de cualquier página ASP.NET, excepto por unas pocas diferencias. El código de servidor de la página debe:

• Implementar la interfaz ICallbackEventHandler. Puede agregar esta declaración de interfaz a cualquier página Web ASP.NET.

• Incluir un método que implemente la interfaz RaiseCallbackEvent. Este método se invocará para realizar la devolución de llamada del servidor.

Además, la página debe contener tres funciones de secuencia de comandos de cliente que realicen las acciones siguientes:

• Una función que llama a un método auxiliar que realiza la solicitud real al servidor. En esta función, puede incluir lógica personalizada para preparar en primer lugar los argumentos de los eventos y, a continuación, puede enviar una cadena como parámetro al controlador de eventos de devolución de llamada del servidor.

• Otra función que recibe (y a la que llama) el resultado del código de servidor que ha procesado el evento de devolución de llamada y acepta una cadena que representa los resultados. Se denomina función de devolución de llamada del cliente.

• La tercera función es una función auxiliar que realiza la solicitud real al servidor, la cual ASP.NET genera automáticamente cuando se crea una referencia a esta función mediante el método GetCallbackEventReference en el código del servidor.

Las devoluciones de llamadas y de datos del cliente son solicitudes de la página originada, así que se graban en los registros de servidor Web como solicitudes de página.

3.2.- Implementar las interfaces adecuadas en el código del servidor Para poder ejecutar correctamente código del servidor desde el cliente sin que se realice ninguna devolución de datos, debe implementar las interfaces adecuadas en el código del servidor.

3.2.1.- Declarar la interfaz ICallbackEventHandler Puede declarar la interfaz ICallbackEventHandler como parte de la declaración de clase para la página. Si crea una página de código subyacente, puede declarar la interfaz utilizando una sintaxis como la siguiente.

public partial class CallBack_DB_aspx : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler Si está trabajando en un control de usuario o una página de un solo archivo, puede agregar la declaración mediante una directiva @ Implements en la página, como en los ejemplos de código siguientes.

Page 44: Teoria Ajax y Aspnet

AJAX y ASP.NET

44 <%@ Page Language="C#" %> <%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

3.2.2.- Crear un método de devolución de llamada En el código del servidor, debe crear un método que implemente el método RaiseCallbackEvent y un método que implemente el método GetCallbackResult. El método RaiseCallbackEvent toma un único argumento de cadena en lugar de los dos argumentos que se suelen utilizar con los controladores de eventos. Una parte de este método podría tener la apariencia del ejemplo de código siguiente.

public void RaiseCallbackEvent(String eventArgument) { return eventArgument + " new value"; }

El método GetCallbackResult no toma ningún argumento y devuelve una cadena. Parte de este método podría ser similar al siguiente ejemplo de código:

public string GetCallbackResult() { return aStringValue; }

3.3.- Crear funciones de secuencia de comandos de cliente Debe agregar funciones de secuencia de comandos de cliente a la página para poder realizar dos funciones: enviar la devolución de llamada a la página del servidor y recibir los resultados. Ambas funciones de secuencia de comandos de cliente están escritas en ECMAScript (JavaScript).

3.3.1.- Enviar la devolución de llamada La función utilizada para enviar la devolución de llamada se genera en el código del servidor. La devolución de llamada real la realiza una función de biblioteca que está disponible para cualquier página que implemente la interfaz ICallbackEventHandler. Para obtener una referencia a la función de biblioteca, llame al método GetCallbackEventReference de la página, al que se puede obtener acceso a través de la propiedad ClientScript de la página. A continuación, cree dinámicamente una función de cliente que incluya una llamada al valor que devuelve el método GetCallbackEventReference. Pase a dicho método una referencia a la página (this en C# o Me en Visual Basic), el nombre del argumento mediante el que pasará los datos, el nombre de la función de secuencia de comandos de cliente que recibirá los datos de la devolución de llamada y un argumento que pasa el contexto deseado.

Cuando haya creado la función, insértela en la página llamando al método RegisterClientScriptBlock.

En el ejemplo de código siguiente se muestra cómo crear dinámicamente una función denominada CallServer que invoca la devolución de llamada.

Page 45: Teoria Ajax y Aspnet

AJAX y ASP.NET

45

void Page_Load(object sender, EventArgs e) { ClientScriptManager cm = Page.ClientScript; String cbReference = cm.GetCallbackEventReference(this, "arg", "ReceiveServerData", ""); String callbackScript = "function CallServer(arg, context) {" + cbReference + "; }"; cm.RegisterClientScriptBlock(this.GetType(), "CallServer", callbackScript, true); }

Los nombres de los argumentos aceptados por la función que está generando deben coincidir con los nombres de los valores pasados al método GetCallbackEventReference.

En el ejemplo de código siguiente se muestra marcado que se puede utilizar para invocar la devolución de llamada y procesar su valor devuelto

<input type="button" value="Callback" onclick="CallServer(1, alert('Callback'))"/> <br /> <span id="Message"></span>

3.3.2.- Recibir la devolución de llamada Puede escribir una función de cliente que reciba las devoluciones de llamada de forma estática en la página. El nombre de la función debe coincidir con el nombre pasado en la llamada al método GetCallbackEventReference. La función receptora acepta dos valores de cadena: uno para el valor devuelto y un segundo valor opcional para el valor de contexto que se devuelve del servidor.

La función podría ser similar al siguiente ejemplo de código:

<script type="text/javascript"> function ReceiveServerData(arg, context) { Message.innerText = 'Processed callback.'; } </script>

3.4.- Ejemplo de implementación de devolución de llamada de cliente El ejemplo de código siguiente se compone de dos partes. La primera parte muestra una página Web ASP.NET (la página .aspx). La segunda parte muestra el archivo de código subyacente correspondiente (el archivo .aspx.cs).

La página Web emula una búsqueda de base de datos para determinar el número de elementos disponibles, o en existencias, para una serie de productos (monitores, teclados, etc.). Para simplificar este ejemplo de código, la base de datos está representada por una lista de diccionario que contiene un pequeño grupo de elementos. Para cada elemento de la tabla,

Page 46: Teoria Ajax y Aspnet

AJAX y ASP.NET

46 la clave es el nombre del elemento (por ejemplo, monitor) y el valor es el número de elementos que hay en existencias. En una aplicación de producción, se utilizaría una base de datos.

Cuando se ejecuta la página, se enlaza un control ListBox a la tabla hash para que el control ListBox muestre la lista de productos. La página también contiene un elemento button (no un control de servidor Web de botón), cuyo evento onclick está enlazado a una función del cliente denominada LookUpStock. Cuando los usuarios hacen clic en el botón, éste ejecuta la función LookUpStock, que obtiene la selección actual del cuadro de lista y, a continuación, realiza la devolución de llamada del cliente llamando a la función CallServer.

La página de código subyacente agrega secuencias de comandos de cliente a la página a través del método RegisterClientScriptBlock. La secuencia de comandos que se agrega a la página incluye una función denominada CallServer, que obtiene el nombre del método que realiza la devolución de datos al servidor desde el método GetCallbackEventReference.

La devolución de llamada del cliente invoca al método RaiseCallbackEvent, que devuelve las existencias disponibles para el producto deseado. Tenga en cuenta que los argumentos enviados entre la secuencia de comandos de cliente y el código del servidor sólo pueden ser cadenas.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="WebApplication1.WebForm2" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <script type="text/javascript"> function LookUpStock() { var lb = document.forms[0].ListBox1; var product = lb.options[lb.selectedIndex].text CallServer(product, ""); } function ReceiveServerData(rValue) { Results.innerText = rValue; } </script> </head> <body> <form id="form1" runat="server" submitdisabledcontrols="False"> <div> <asp:ListBox ID="ListBox1" Runat="server"></asp:ListBox> <br /> <br /> <br /> <br /> Items in stock: <span ID="Results"></span> <br /> </div> </form>

Page 47: Teoria Ajax y Aspnet

AJAX y ASP.NET

47 <button onclick="LookUpStock()">Look Up Stock</button> </body> </html>

using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; namespace WebApplication1 { public partial class WebForm2 : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler { protected System.Collections.Specialized.ListDictionary catalog; protected void Page_Load(object sender, EventArgs e) { String cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context"); String callbackScript; callbackScript = "function CallServer(arg, context)" + "{ " + cbReference + "} ;"; Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CallServer", callbackScript, true); catalog = new System.Collections.Specialized.ListDictionary(); catalog.Add("monitor", 12); catalog.Add("laptop", 10); catalog.Add("keyboard", 23); catalog.Add("mouse", 17); ListBox1.DataSource = catalog; ListBox1.DataTextField = "key"; ListBox1.DataBind(); } #region Miembros de ICallbackEventHandler #endregion #region Miembros de ICallbackEventHandler public string GetCallbackResult() { return returnValue;

Page 48: Teoria Ajax y Aspnet

AJAX y ASP.NET

48 } #endregion #region Miembros de ICallbackEventHandler String returnValue; void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument) { if (catalog[eventArgument] == null) { returnValue = "-1"; } else { returnValue = catalog[eventArgument].ToString(); } } #endregion } }

3.- Leer Tiempo del Servidor usando Callback Usando callbacks podemos desde el código del servidor leer el resultado de una función JavaScript. Elaborar una respuesta, y con este resultado actualizar la página ASP sin postback. Básicamente, un callback es un dialogo entre el código JavaScript de la página y el código .NET del servidor.

Para usar un Callback de ASP.NET 2.0 necesitamos usar el siguiente esquema, siendo el mismo para cualquier solución:

1. Implementar la interfaz ICallbackEventHandler

2. Configurar las retrollamadas en Page_Load

3. Escribir respuesta en RiseCallbackEvent, proceso de negocios

4. Enviar respuesta en GetCallbackResult

5. Escribir respuesta en la página

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="tiemposervidorcallback._Default" %>

Page 49: Teoria Ajax y Aspnet

AJAX y ASP.NET

49 <!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 runat="server"> <title>Diferencia Horaria</title> <script type="text/javascript" src="ClientTime.js"></script> <script type="text/javascript" src="CallbackComplement.js"></script> <script type="text/javascript"> function timerEvent() { callServerTask(); window.setTimeout("timerEvent()",1500); return false; } </script> </head> <body onload="window.setTimeout('timerEvent()',1500);"> <form id="form1" runat="server"> <div> <h2> Diferencia Horaria</h2> <hr /> <div id="div_CallbackResult"> <asp:TextBox ID="txtClientTime" runat="server" Width="343px" /> <br /> <asp:TextBox ID="txtServerTime" runat="server" Width="341px" /> </div> <hr /> </div> </form> </body> </html>

Notamos que se invoca una función JavaScript de nombre callServerTask la cual no existe en la página. La función callServerTask será escrita por el código del lado del servidor.

1. Implementar la interfaz ICallbackEventHandler

La implementación de la interfaz ICallbackEventHandler capacita a la página Web a usar Callbacks de ASP.NET 2.0. La interfaz habilita los eventos: RaiseCallbackResult y GetCallbackResult los cuales se configuran para usar dos subrutinas de JavaScript, una que llama a RaiseCallbackResult y la otra que toma una respuesta elaborada enviada por GetCallbackResult. Implementamos la interfaz al heredar de ICallbackEventHandler en C#, o al agregar la directiva “Implements ICallbackEventHandler” en VB.NET.

Se recomienda que siempre se agregue la variable a nivel de modulo de nombre “_callbackResult” para C# o “m_CallbackResult” para VB.NET. Aunque el nombre es a libre

Page 50: Teoria Ajax y Aspnet

AJAX y ASP.NET

50 albedrio, podemos generalizar un nombre para simplificar el asunto. Así, el código de GetCallbackResult() puede ser el mismo en cada aplicación que use callbacks, solo se hace un retorno de m_CallbackResult.

2. Configurar las retrollamadas en Page_Load

La configuración del callback se hace en el evento Page_Load. Debemos generar una línea de código que se agregará dinámicamente a la página y es la encargada del callback. ASP.NET facilita esto a través del metodo GetCallbackEventReference.

Atención a los argumentos de GetCallbackEventReference. El primero es el objeto contenedor, es decir, this para C#, y Me para VB.NET. El segundo, clientTime('') en el ejemplo, es argumento el cual será pasado a RaiseCallbackEvent. Este argumento puede variar según el contexto de la aplicación. El tercer argumento, putCallbackResult, es la función que se invocará desde GetCallbackResult pasando m_CallbackResult como argumento de putCallbackResult, es decir, se pasan datos del código del servidor al código del cliente. Los demás argumentos son opcionales. En particular, es conveniente agregar una función que reporte un posible error en el callback. Se ha generalizado este nombre a clientErrorCallback.

Al final de Page_Load usamos RegisterClientScriptBlock el cual es el método encargado de enviar la fuente de texto script a la pagina.

Normalmente en al final de Page_Load agregamos un atributo a un control para habilitar un evento que será el responsable de llamar la funcion callServerTask(). En este caso no es necesario ya que callServerTask() es llamada desde la function timerEvent().

El resultado de GetCallbackEventReference se puede visualizar en el código de la pagina leida por el visualizador de internet. Realmente la complejidad no es algo que nos deba preocupar. He aquí el código generado a manera de ilustración:

function callServerTask() { WebForm_DoCallback('__Page',clientTime(''), putCallbackResult,null,clientErrorCallback,true); }

3. Escribir respuesta en RiseCallbackEvent

RiseCallbackEvent es una función que se invoca desde la página al servidor sin postbak. Un script de JavaScript coloca el argumento eventArgument de RiseCallbackEvent el cual es una cadena de texto de JavaScript. En RiseCallbackEvent procesamos esta cadena para generar una respuesta HTML. En una aplicación de producción, eventArgument suele contener el valor de una clave para filtrar una vista de datos.

En seguida procesamos eventArgument, es decir hacemos lo que en ingles se conoce como parsing, que no es más que extraer información de una cadena de texto. Luego elaboramos una respuesta HTML.

Page 51: Teoria Ajax y Aspnet

AJAX y ASP.NET

51 4. Enviar respuesta en GetCallbackResult

La cadena o fuente HTML generada como respuesta es asignada a m_CallbackResult, la cual a su vez es retornada inmediatamente a la pagina a través de GetCallbackResult.

5. Escribir respuesta en la página

La pagina ahora tiene el resultado del callback en la variable m_CallbackResult que ahora es un argumento de putCallbackResult, y este escribe la division 'div_CallbackResult'. El nombre 'div_CallbackResult' también es definido por el programador. Como se ha venido comentando, si usamos un nombre generalizado como 'div_CallbackResult' podemos hacer más simple la programación AJAX. He usado una etiqueta DIV la cual encierra toda la respuesta HTML. No necesariamente tiene que ser una etiqueta DIV, puede ser cualquier objeto HTML. Solo se trata de generalizar para simplificar.

Para hacer simplificar código en la página las funciones putCallbackResult y clientErrorCallback se pueden colocar en un archivo JScript e incrustar en la página con una directiva src. El archivo será un ítem más de la aplicación Web. Se ha llamado a este archivo “CallBackComplement.js”. He aquí su código:

// JScript File function putCallbackResult( callbackResult ) { var info = document.getElementById('div_CallbackResult'); info.innerHTML = callbackResult; } function clientErrorCallback( error, context ) { alert('Callback failed! ' + error); }

Serialización JSON JSON (notación de objetos JavaScript) es un formato de codificación de datos eficaz que permite intercambios rápidos de cantidades pequeñas de datos entre los exploradores de cliente y servicios web con AJAX (JavaScript asincrónico y XML) habilitado.

En este tema se muestra cómo serializar objetos de tipo .NET en datos codificados mediante JSON y, a continuación, deserializar los datos en formato JSON en instancias de tipos .NET mediante el DataContractJsonSerializer. En este ejemplo, se usa un contrato de datos para mostrar la serialización y deserialización de un tipo Person definido por el usuario.

Para definir el contrato de datos de una Persona Defina el contrato de datos para Person asociando DataContractAttribute a la clase y el atributo DataMemberAttribute a los miembros que desee serializar.

Page 52: Teoria Ajax y Aspnet

AJAX y ASP.NET

52 [DataContract] internal class Person { [DataMember] internal string name; [DataMember] internal int age; }

Agregaremos una referencia a System.ServiceModel.Web y a System.Runtime.Serialization

E incluiremos

using System.Runtime.Serialization.Json; using System.Runtime.Serialization;

Para serializar una instancia de tipo Persona a JSON

Cree una instancia del tipo Person

.

Person p = new Person(); p.name = "John"; p.age = 42;

Serialice el objeto Person a una secuencia de memoria utilizando el DataContractJsonSerializer.

MemoryStream stream1 = new MemoryStream(); DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));

Utilice el método WriteObject para escribir datos JSON en la secuencia.

ser.WriteObject(stream1, p);

Muestre la salida JSON.

stream1.Position = 0; StreamReader sr = new StreamReader(stream1); Mensaje.Text=sr.ReadToEnd();

Deserialización de una instancia de tipo Persona a partir de JSON

Page 53: Teoria Ajax y Aspnet

AJAX y ASP.NET

53 Deserialice los datos codificados con JSON en una nueva instancia de Person utilizando el método ReadObject de DataContractJsonSerializer

:

stream1.Position = 0; Person p2 = (Person)ser.ReadObject(stream1);

Muestre los resultados. Mensaje2.Text=p2.name; Mensaje2.Text+="\r\n, age="; Mensaje2.Text=p2.age.ToString();

El ASP.NET AJAX Control Toolkit Accordion El control Web Accordion te permite ubicar múltiples paneles, de modo que únicamente uno será visible en cada momento. Dichos paneles son los AccordionPane, de los que debemos definir la cabecera (Header) y el contenido (Content). El estado del Accordion es guardado, de modo que el AccordionPane activo se mantendrá visible a través de los postbacks.

9 propiedades definen al Accordion: • SelectedIndex: Define el AccordionPane que estará activo por defecto, donde el primero tiene como índice 0. Es opcional y por defecto vale 0. • HeaderCssClass / ContentCssClass: Identifica el nombre de la clase CSS utilizada para las cabeceras/contenidos (Header/content). Si se define como atributo del Accordion, la clase se aplicará por defecto a todos los AccordionPane de que esté compuesto. También se puede definir individualmente como atributo de cada AccordionPane. • FadeTransitions: en caso de ser true se aplicacará un efecto de fading en la transición, en caso de ser false la transición se realizará de modo normal. Es optativo y por defecto vale false. • TransitionDuration: cantidad de milisegundos que definen la duración de una transición. Se consigue un efecto muy agradeble con transición de unos 200-300 milisegundos. • FramesPerSecond: número de frames por segundo que se usará en la animación de las transiciones. Suele ser suficiente un número superior a 40. • AutoSize: define la restricción en la altura del Accordion. Puede tomar tres valores: o None: No tiene ninguna restricción. La altura del Accordion no tiene límite. Es importante reseñar que esto puede implicar que otros elementos de la misma Web sean movidos. o Limit: como máximo, el Accordion medirá lo que marque la propiedad Height. Si el Accordion es más alto de lo que marque su Height, al AccordionPane activo se le añadirá un scroll para ajustarse al límite. En caso de ser menor a ese límite el Accordion no sufre cambios. o Fill: el Accordion siempre medirá lo que marqué su propiedad Height, expandiendo o minimizando el contenido en base a las necesidades. • Header: es una propiedad del AccordionPane y define el valor de su cabecera.

Page 54: Teoria Ajax y Aspnet

AJAX y ASP.NET

54 • Content: es una propiedad del AccordionPane y define el valor de su contenido. • DataSource: El DataSource a aplicar (totalmente optativo). Para una correcta aplicación hay que llamar a DataBind(). • DataSourceID: – Alternativamente, poder asignar el identificador de nuestra fuente de datos. • DataMember: el miembro a enlazar cuando se usa el DataSourceID.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ACT-Accordion.aspx.cs" Inherits="Accordion_ACT_Accordion" %> <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %> <!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 runat="server"> <title>Accordion</title> <style> .accordionCabecera { border: 1px solid black; background-color: #ffd800; font-family: Arial, Sans-Serif; font-size: 14px; font-weight: bold; padding: 4px; margin-top: 4px; cursor: pointer; } .accordionContenido { font-family: Sans-Serif; background-color: #fff8ab; border: 1px solid black; border-top: none; font-size: 12px; padding: 7px; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager id="ScriptManager" runat="server" /> <ajaxToolkit:Accordion ID="Accordion1" runat="server" FadeTransitions="True" FramesPerSecond="50"

Page 55: Teoria Ajax y Aspnet

AJAX y ASP.NET

55 Width="250px" TransitionDuration="200" HeaderCssClass="accordionCabecera" ContentCssClass="accordionContenido"> <Panes> <ajaxToolkit:AccordionPane ID="AccordionPane1" runat="server"> <Header>Panel 1</Header> <Content>Contenido 1</Content> </ajaxToolkit:AccordionPane> <ajaxToolkit:AccordionPane runat="server"> <Header>Panel 2</Header> <Content>Contenido 2</Content> </ajaxToolkit:AccordionPane> <ajaxToolkit:AccordionPane runat="server"> <Header>Panel 3</Header> <Content>Contenido 3</Content> </ajaxToolkit:AccordionPane> </Panes> </ajaxToolkit:Accordion> </div> </form> </body> </html>

AlwaysVisibleControl

Descripción El AlwaysVisibleControl es uno de los controles Web del ASP.NET AJAX Control Toolkit más simples. Su funcionalidad consiste en dejar clavado el contenido en un punto específico de la página. Un ejemplo sería el que cierto mensaje se muestre siempre en la parte inferior derecha de nuestra página, y que se mantenga en la misma posición de la pantalla del usuario cuando se haga scroll sobre la página.

Propiedades • TargetControlID: ID del control que queremos que el AlwaysVisibleControl clave en la posición que determinemos. Habitualmente suele tratarse de un “Panel”. • HorizontalSide: ubicación horizontal (derecha o izquierda) donde se clavará el control. Es una propiedad optativa que por defecto vale left. HorizontalOffset: distancia horizontal en pixels desde el objeto hasta el lado que definamos en el HorizontalSide. Es optativo y por defecto vale 0 px. • VerticalSide: ubicación vertical (arriba o abajo) donde se clavará el control. Es una propiedad optativa que por defecto vale top. • VerticalOffset: distancia vertical en pixels desde el objeto hasta el lado que definamos en el VerticalSide. Es optativo y por defecto vale 0 px. • ScrollEffectDuration: define la cantidad de segundos entre que la página hace scroll hasta que el control se posiciona donde definamos. Por defecto vale 0.1 segundos y siempre debe ser mayor que cero.

Page 56: Teoria Ajax y Aspnet

AJAX y ASP.NET

56 Ejemplo <asp:Panel ID="Panel1" runat="server" Height="50px" Width="125px"> de mensaje </asp:Panel> <ajaxToolkit:AlwaysVisibleControlExtender ID="AlwaysVisibleControlExtender1" runat="server" TargetControlID="Panel1" VerticalSide="Bottom" VerticalOffset="10" HorizontalSide="Right" HorizontalOffset="10" ScrollEffectDuration="0.0001"> </ajaxToolkit:AlwaysVisibleControlExtender>

Animation Y para el final dejamos dos controles que son, sin duda alguna, los más espectaculares del ASP.NET AJAX Control Toolkit. El primero de todos es el Animation. El Animation es un extendedor que permite aplicar sobre el elemento elegido las animaciones que nos permiten el Animation Framework. El Animation Framework es una aquitecturo de animaciones creadas para ASP.NET AJAX y que, a pesar de no ser demasiado complicadas, merecerían un artículo completo para su correcta explicación. A modo de tanteo, diremos que las animaciones proporcionadas por el Animation Framework y que podremos aplicar con nuestro extendedor Animation, nos permiten asignar efecto de “fadeIn” y “fadeOut”, “pulse”, “Scale” o acciones javascript, tanto en modo secuencia, en modo paralelo o cualquier combinación imaginable de las dos.

Propiedades • TargetControlID: ID del control a partir del cual y sobre el cual vamos a aplicar las animaciones. • OnLoad: elemento bajo el cual añadiremos las animaciones que se iniciarán tras la carga del control. • OnClick: elemento bajo el cual añadiremos las animaciones que se iniciarán hacer click sobre el control. • OnMouseOver: elemento bajo el cual añadiremos las animaciones que se iniciarán tras pasar el mouse sobre el control. • OnMouseOut: elemento bajo el cual añadiremos las animaciones que se iniciarán tras sacar el mouse de encima del control. • OnHoverOver: Similar a OnMouseOver, solo que parará la animación OnHoverOut antes de ejecutarse. • OnHoverOut: Similar a OnMouseOut, solo que parará la animación OnHoverOver antes de ejecutarse.

Ejemplo Apliquemos el uso del control Animation. Para aprender a usar animaciones, se recomienda visitar la web oficial, donde encontraremos ejemplos de uso y una referencia completa: - http://ajax.asp.net/ajaxtoolkit/Walkthrough/UsingAnimations.aspx - http://ajax.asp.net/ajaxtoolkit/Walkthrough/AnimationReference.aspx

Page 57: Teoria Ajax y Aspnet

AJAX y ASP.NET

57 <asp:Panel ID="Panel1" runat="server" Width="125px" BorderWidth="1px" BackColor="Yellow"> Pasa por encima mío y luego vete. También puedes hacerme clic ;) </asp:Panel> <ajaxToolkit:AnimationExtender id="MyExtender" runat="server" TargetControlID="Panel1"> <Animations> <OnMouseOver> <FadeOut Duration="2.5" Fps="20" /> </OnMouseOver> <OnMouseOut> <FadeIn Duration=".5" Fps="20" /> </OnMouseOut> <OnClick> <Sequence> <Pulse Duration=".1" /> <Parallel Duration=".5" Fps="30"> <FadeOut /> <Scale ScaleFactor="5" Unit="px" Center="true" ScaleFont="true" FontUnit="pt" /> </Parallel> </Sequence> </OnClick> </Animations> </ajaxToolkit:AnimationExtender>

Calendar Calendar es un extensor ASP.NET AJAX que se puede conectar a cualquier TextBox de ASP.NET de control. Ofrece al cliente la fecha la recolección de lado la funcionalidad con la fecha personalizable formato y la interfaz de usuario en un control de ventanas emergentes. Usted puede interactuar con el calendario haciendo clic en el día a fijar la fecha, o el "Hoy" para establecer la fecha actual.

Además, las flechas izquierda y derecha se puede utilizar para avanzar o retroceder un mes. Al hacer clic en el título del calendario que puede cambiar la vista de los Días en la mes en curso, a meses en el año en curso. Otro clic va a cambiar a los años En la década actual. Esta acción le permite saltar fácilmente a las fechas en el pasado o en el futuro desde el control de calendario.

• TargetControlID•

- El ID del cuadro de texto para ampliar con el calendario. CssClass

- Nombre de la clase CSS utilizado para el estilo del calendario. Ver la sección del Calendario Tematización para más información. Formato - Formato de cadenas se utiliza para mostrar la fecha seleccionada.

• PopupButtonID

- La identificación de un control para mostrar la ventana emergente de calendario de cuando se hace clic. Si este valor no está establecido, el calendario aparecerá en el cuadro de texto recibe el foco. PopupPosition

- Indica que el calendar popup debe aparecer en el BottomLeft (por defecto), BottomRight, topLeft, topright, izquierda o derecha del cuadro de texto. SelectedDate - Indica la fecha del calendario es el extensor inicializa con.

Page 58: Teoria Ajax y Aspnet

AJAX y ASP.NET

58 AsyncFIleUpload AsyncFileUpload es un control de ASP.NET AJAX que permite subir archivos de forma asíncrona con el servidor.

El archivo de los resultados de la carga se puede comprobar tanto en el servidor y los lados del cliente.

Puede guardar el archivo cargado llamando a la SaveAs () en un controlador para el evento de servidor UploadedComplete.

Eventos

• UploadedComplete - Disparó contra el lado del servidor cuando el archivo cargado correctamente

• UploadedFileError - Es despedido en el lado del servidor cuando el archivo uloaded está dañado

Propiedades

• CompleteBackColor - Color de fondo del control sobre la carga completa. El valor por defecto -- 'Cal'.

• ContentType - Obtiene el tipo de contenido MIME de un archivo enviado por un cliente.

• ErrorBackColor - Color de fondo del control en caso de error de carga. El valor por defecto -- 'Rojo'.

• FileContent - Obtiene un Corriente objeto que apunta a un archivo subido a prepararse para leer el contenido del archivo.

• NombreDeArchivo - Obtiene el nombre de un archivo en un cliente a cargar con el control.

• HasFile - Obtiene un bool valor que indica si el control contiene un archivo. • OnClientUploadComplete - El nombre de una función de JavaScript ejecutado

en el lado del cliente después de que el archivo subido correctamente • OnClientUploadError - El nombre de una función de JavaScript ejecutado

en el lado del cliente si la carga de archivos no • OnClientUploadStarted - El nombre de una función de JavaScript ejecutado

en el lado del cliente en la carga de archivos iniciado • PostedFile - Obtiene un HttpPostedFile objeto que proporciona acceso al

archivo cargado. • ThrobberID - ID de control que se muestra mientras el archivo se carga. • UploaderStyle - Estilo de la apariencia del control (tradicional, moderna).

El valor por defecto -- "Tradicional". • UploadingBackColor - Color de fondo del control cuando la carga está en

progreso. El valor por defecto -- 'Blanco'. • Anchura - Ancho del control (Unidad). El valor por defecto -- '355px

'.

Métodos

Page 59: Teoria Ajax y Aspnet

AJAX y ASP.NET

59 • SaveAs (cadena nombre de archivo) - Guarda el contenido de un archivo

cargado.

CascadingDropDown Imaginemos un escenario en que tenemos 3 listas desplegables. La primera de ellas tiene unos items determinados, pero la segunda lista depende del valor que se le dé a la primera y la tercera lista del valor que se le dé a la segunda. Hasta ahora teníamos dos opciones: - Implementar una compleja serie de funciones javascript, - Utilizar ASP.NET recargando las páginas. En el primer caso quedaba muy profesional de cara al cliente, pues éste manejaba muchos datos de forma muy rápida y sin recargar la página... sin embargo era muy poco profesional del cara al programador pues la complejidad en el javascript se incrementaba exponencialmente. En el segundo caso el programador conseguía una programa estable, rápido y fácilmente modificable, pero el usuario veía cómo se recargaba la página entera cada vez que elegía una opción diferente. Pues bien, con el CascadingDropDown solucionamos los problemas y nos quedamos con las ventajas: no se recargará la página y se definirá el contenido de los DropDownList mediante ASP.NET

Propiedades • TargetControlID: el ID de la lista desplegable a la que se aplicará. • Category: se define como el nombre de la categoría que la lista desplegable representa. Su utilidad será la de representar uno de los dos parámetros de entrada al ServiceMethod que estudiaremos posteriormente • PromptText: es un texto opcional que verá el usuario cuando la lista desplegable esté vacía. • LoadingText: también es un texto opcional que verá el usuario cuando el dato se está cargando. • ServicePath: define el path del servicio web que devuelve la información que se usará para rellenar la lista desplegable. Si el servicio web se encuentra en la propia página en que estamos trabajando, no pondremos nada en esta propiedad. • ServiceMethod: le dedicamos un apartado exclusivo • ParentControlID: ID de la lista desplegable de cuya selección depende esta lista desplegable. En nuestro ejemplo, si esta es la lista desplegable 2, el ParentControlID apuntaría a la lista desplegable 2. Gracias a ParentControlId creamos una jerarquía de listas desplegables. En caso de estar en lo más alto de la jerarquía no pondríamos nada. • SelectedValue: valor que vendría seleccionado por defecto. Es opcional.

Page 60: Teoria Ajax y Aspnet

AJAX y ASP.NET

60 ServiceMethod El es la función a la que se llamará para rellenar la lista desplegable. Tendrá el siguiente aspecto: [WebMethod] public CascadingDropDownNameValue[] GetDropDownContents(string knownCategoryValues, string category){...} ...donde lo único que se podrá cambiar será el nombre de la función, pues el resto debe ser igual. Observamos que: • La función debe ir precedida por [WebMethod]. • CascadingDropDownNameValue es un tipo de dato dentro del namespace AjaxControlToolkit (que en nuestro ejemplo suponemos ya importado mediante using (C#) o import (VB)). • El segundo parámetro (category) se corresponde con el atributo Category que hemos indicado en nuestro control CascadingDropDown. Mención especial merece el primer parámetro. En éste se almacena el valor seleccionado de cada una de las listas desplegables predecesoras en la jerarquía. Siguiendo con nuestro ejemplo, si estuviéramos dentro del definido en la lista desplegable 3, el contenido del primer parámetro sería similar a: Category1:valor1;category2:valor2 Pero no cabe asustarse, no hace falta que parseemos a mano esa información, pues dispondemos del método ParseKnownCategoryValuesString que hará ese trabajo por nosotros, de modo que haciendo: StringDictionary knownCategoryValuesDictionary = AjaxControlToolkit .CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues); ... obtenemos un StringDictionary bien ordenado y sencillo de utilizar.

Ejemplo Nota 1: hay que importar los siguientes namespaces: - System.Web.Services - AjaxControlToolkit - System.Collections.Specialized Nota 2: EnableEventValidation debe valer false El uso avanzado del CascadingDropDownList implica un estudio más en profundidad de todas sus características. En los diferentes blogs tecnológicos encontramos diferentes ejemplos en los que se configura la fuente de datos de diferentes listas desplegables mediante XML o ases de datos. Nosotros mostramos un sencillo ejemplo para que el lector se agilice en el uso del CascadingDropDown y pueda acceder a ejemplos mucho más complejos. Nuestro ejemplo consta de dos listas desplegables, donde la segunda depende de la primera.

Page 61: Teoria Ajax y Aspnet

AJAX y ASP.NET

61 En el momento hacemos una selección en la primera lista desplegable el mecanismo del CascadingDropDown entra en funcionamiento y se rellena la segunda lista desplegable sin que la página se recargue. CascadingDropDown.aspx <atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"> </atlas:ScriptManager> <asp:DropDownList ID="DropDownList1" runat="server"> <asp:ListItem Text="Elige tu humor y te aconsejaré tu color" Value="-1"> </asp:ListItem> <asp:ListItem Text="Triste" Value="Triste"> </asp:ListItem> <asp:ListItem Text="Alegre" Value="Alegre"> </asp:ListItem> </asp:DropDownList> <br /> <asp:DropDownList ID="DropDownList2" runat="server"> </asp:DropDownList> <br /> <ajaxToolkit:CascadingDropDown ID="CascadingDropDown2" runat="server" TargetControlID="DropDownList2" Category="color" ServiceMethod="" ParentControlID="DropDownList1"> </ajaxToolkit:CascadingDropDown> CascadingDropDown.aspx.cs [WebMethod] public CascadingDropDownNameValue[] (string knownCategoryValues, string category) { CascadingDropDownNameValue[] respuesta = new AjaxControlToolkit .CascadingDropDownNameValue[2]; if (category == "color") { StringDictionary knownCategoryValuesDictionary = AjaxControlToolkit .CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues); if (DropDownList1.SelectedValue != "-1") { if (DropDownList1.SelectedValue == "Alegre") { respuesta[0] = new CascadingDropDownNameValue("Amarillo", "Amarillo"); respuesta[1] = new CascadingDropDownNameValue("Naranja", "Naranja"); } else if (DropDownList1.SelectedValue == "Triste") {

Page 62: Teoria Ajax y Aspnet

AJAX y ASP.NET

62 respuesta[0] = new CascadingDropDownNameValue("Gris", "Gris"); respuesta[1] = new CascadingDropDownNameValue("Azul marino", "Azul_marino"); } } } return respuesta; }

CollapsiblePanel Con el CollapsiblePanel conseguiremos que cualquier control ASP.NET pueda ser maximizado o minimizado a nuestro antojo. Distinguiremos entre el contenido, que será el control que vaya a cerrarse y abrirse (por ejemplo un Panel) y el controlador, que será el control sobre el que deberemos hacer clic para cerrar y/o abrir el contenido. El estado del contenido (abierto o cerrado) es guardado a lo largo de los postbacks, por lo que permanecerá igual cuando recarguemos una página. Además, podemos especificar si queremos que el contenido tenga una altura y/o anchura determinadas, o por el contrario permitimos que se dimensione como requiera.

Propiedades • TargetControlID: el ID del control Web correspondiente al contenido. • CollapsedSize: el tamaño en pixels del contenido cuando está cerrado. Lo habitual es ponerlo a 0, de modo que queda totalmente cerrado. • ExpandedSize: el tamaño en pixels del contenido cuando esté abierto. • Collapsed: especifica el estado del contenido cuando se inicializa la página. Puede ser collapsed (cerrado) o expanded (abierto). • Scroll Contents: si especificamos true, se añadirá una barra de scroll cuando el tamaño sobrepaso al especificado en CollapsedSize y ExpandedSize. Si no queremos que se produzca ningún efecto, lo pondremos a false. • ExpandControlID/CollapseControlID: el ID del control Web correspondiendo al controlador. Como vemos podemos elegir un controlador que maximice el contenido y otro que lo minimice. Habitualmente ambos atributos apuntan al mismo controlador. • TextLabelID: el ID de la Label donde se especificará el estado en que se encuentra el contenido (ver las dos próximas propiedades). • CollapsedText: texto que se mostrará en la Label especificada en TextLabelId cuando el controlador esté cerrado. • ExpandedText: texto que se mostrará en la Label especificada en TextLabelId cuando el controlador esté abierto. • ImageControlID: En lugar de un texto, podemos especificar una imagen para que sea ésta la que describa el estado en que se encuentra el contenido. Si además también hemos especificado un texto, éste se corresponderá con el texto alternativo de la imagen (el atributo “alt”). • CollapsedImage: Path que apunta a la imagen que se mostrará cuando el contenido esté minimizado. • ExpandedImage: Path que apunta a la imagen que se mostrará cuando el contenido esté maximizado.

Page 63: Teoria Ajax y Aspnet

AJAX y ASP.NET

63 • ExpandDirection: podemos definir que el contenido se abra de arriba a abajo o de izquierda a derecha. En el primer caso asignaremos “Vertical” y en el segundo “Horizontal”.

Ejemplo <asp:Label ID="Label1" runat="server" Text="Label" CssClass="CP"></asp:Label> <asp:Panel ID="Panel1" runat="server" Width="120px"> Este es el contenido que será abierto o cerrado mediante el controlador, que se corresponde con el texto de arriba. Éste a su vez describirá el estado. </asp:Panel> <ajaxToolkit:CollapsiblePanelExtender ID="CollapsiblePanelExtender1" runat="server" TargetControlID="Panel1" CollapsedSize="0" ExpandedSize="300" Collapsed="True" ExpandControlID="Label1" CollapseControlID="Label1" TextLabelID="Label1" CollapsedText="Abrir contenido" ExpandedText="Cerrar contenido" ExpandDirection="Vertical"/> </ajaxToolkit:CollapsiblePanelExtender>

ConfirmButton Con el ConfirmButton conseguimos una sencilla funcionalidad. Lo asignaremos a un Button, LinkButton o Hyperlink, de modo que cuando se haga clic sobre éste, el navegador nos muestre una ventana de confirmación. En ésta deberemos elegir “sí” o “no” para que se ejecute o no el evento asociado al control en cuestión.

Propiedades • TargetControlID: ID del control al que aplicaremos el efecto el ConfirmButton. • ConfirmText: texto que se mostrará al presionar sobre el control. Por ejemplo “¿Realmente desea ejecutar…?”

Ejemplo Mostraremos un botón que se ocupará de recargar la página. Cuando se nos muestre la ventana de confirmación elegiremos si realmente deseamos recargarla o no. <asp:Button ID="Button1" runat="server" Text="Recargar página" /> <ajaxToolkit:ConfirmButtonExtender ID="ConfirmButtonExtender2" runat="server" TargetControlID="Button1" ConfirmText="¿Realmente desea recargar la página?" /> </ajaxToolkit:ConfirmButtonExtender>

DragPanel El DragPanel sería el ejemplo perfecto de cómo conseguir una funcionalidad avanzada, que en javascript requeriría decenas de líneas de programación, con apenas dos líneas de código y una mayor flexibilidad.

Page 64: Teoria Ajax y Aspnet

AJAX y ASP.NET

64 Se aplica a cualquier control Web (el más habitual es el Panel) y le añade la funcionalidad de poder arrastrarlo a cualquier parte de la pantalla. Vamos a distinguir entre el controlador y el contenido, donde el controlador es sobre lo que deberemos hacer clic y arrastrar para mover el contenido.

Propiedades • TargetControlID: el ID del control correspondiente al contenido. • DragHandleID: el ID del control correspondiente al controlador.

Ejemplo <asp:Panel ID="Panel3" runat="server" Height="50px" Width="125px"> <asp:Panel ID="Panel1" runat="server" Width="125px" BackColor="Yellow" Font-Bold="true" BorderColor="black" BorderWidth="1"> Arrástrame </asp:Panel> <asp:Panel ID="Panel2" runat="server" Height="250px" Width="125px" BorderColor="black" BorderWidth="1"> Este es el contenido que vamos a poder arrastrar por toda la pantalla. </asp:Panel> </asp:Panel> <ajaxToolkit:DragPanelExtender ID="DragPanelExtender1" runat="server" DragHandleID="Panel1" TargetControlID="Panel3"> </ajaxToolkit:DragPanelExtender> <script type="text/javascript"> // Pequeño script para una correcta compatibilidad con todos los navegadores. function setBodyHeightToContentHeight() { document.body.style.height = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight)+"px"; } setBodyHeightToContentHeight(); $addHandler(window, "resize", setBodyHeightToContentHeight); </script>

DropDown Un sencillo control que le da un aspecto muy avanzado y profesional a nuestra página, así como resultar se muy útil. Consiste en hacer aparentar un DropDown donde no lo hay. Por ejemplo, imaginemos que tenemos dos paneles y que al hacer click sobre uno queremos que aparezca el segundo panel del mismo modo que aparece el contenido de una lista desplegable (en la imagen lo veremos mejor.

Propiedades • TargetControlID: ID del control sobre el que aplicaremos los efectos. Normalmente será un Panel, pero puede ser cualquier cosa. • DropDownControlID: El Id del Panel que será mostrado como una lista desplegable.

Ejemplos <asp:Label ID="TextLabel" runat="server" Text="Ponte sobre mí" Font-Names="Tahoma" Font-Size="11px" Style="display: block; width: 300px; padding:2px; padding-right: 50px;" />

Page 65: Teoria Ajax y Aspnet

AJAX y ASP.NET

65 <asp:Panel ID="DropPanel" runat="server" Style="display:none;visibility:hidden; font-family:Tahoma; font-size: 11px; padding:5px;"> Aquí puede haber cualquier control: imágenes, MultiViews... lo que queráis!!<br /> Por ejemplo, pongamos un Calendario: <br /> <br /> <asp:Calendar ID="Calendar1" runat="server" BackColor="White" BorderColor="#999999" CellPadding="4" DayNameFormat="Shortest" Font-Names="Verdana" Font-Size="8pt" ForeColor="Black" Height="180px" Width="200px"> <SelectedDayStyle BackColor="#666666" Font-Bold="True" ForeColor="White" /> <TodayDayStyle BackColor="#CCCCCC" ForeColor="Black" /> <SelectorStyle BackColor="#CCCCCC" /> <WeekendDayStyle BackColor="#FFFFCC" /> <OtherMonthDayStyle ForeColor="#808080" /> <NextPrevStyle VerticalAlign="Bottom" /> <DayHeaderStyle BackColor="#CCCCCC" Font-Bold="True" Font-Size="7pt" /> <TitleStyle BackColor="#999999" BorderColor="Black" Font-Bold="True" /> </asp:Calendar> <br /> Si pusiéramos el calendarios sobre un UpdatePanel... podríamos hacer maravillas ;) </asp:Panel> <ajaxToolkit:DropDownExtender runat="server" ID="DDE" TargetControlID="TextLabel" DropDownControlID="DropPanel" />

DropShadow El DropShadow extiende al control Panel con dos características muy interesantes: - Añade una sombra, permitiéndonos definir tanto su profundidad como su oscuridad. - Crea un efecto de redondeado del Panel. Por consiguiente, conseguimos dos efectos muy profesionales de forma tremendamente sencilla.

Propiedades • TargetControlID: ID del Panel sobre el que aplicaremos los efectos. • Width: profundidad en pixels de la sombra. Es un parámetro opcional que por defecto vale 5. • Opacity: valor decimal en tre 0 y 1 que define la opacidad de la sombra, donde el 0 corresponde a transparencia total y 1.0 a completamente opaco. También es opcional y su valor por defecto es 0.5. • TrackPosition: lo pondremos a true si nuestro panel lo hemos definido con posición absoluta o si va a poder ser movido. En caso contrario pondremos false (o no ponemos nada). • Rounded: Si queremos un efecto de redondeado lo pondremos a true, sino, vale con ponerlo a false.

Page 66: Teoria Ajax y Aspnet

AJAX y ASP.NET

66 Ejemplo <asp:Panel ID="Panel1" runat="server" Width="125px" BackColor="Yellow" Font-Names="Arial"> <div style="padding:5px"> En este panel podemos poner lo que queramos. El efecto de sombreado + bordeado es muy agradable a la vista. </div> </asp:Panel> <ajaxToolkit:DropShadowExtender ID="DropShadowExtender1" runat="server" Opacity="1" Width="5" TargetControlID="Panel1" Rounded="true"> </ajaxToolkit:DropShadowExtender>

FilteredTextBox El FilteredTextBox extiende al TextBox de modo que podemos definir qué tipo de caracteres permitimos que escriba el usuario. Elegiremos entre estas configuraciones y sus múltiples combinaciones: - Numbers: todos los números - LowercaseLetters: letras minúsculas. - UppercaseLetters: letras mayúsculas. - Custom: los caracteres que definamos.

Propiedades • TargetControlID: ID del TextBox sobre el que vamos a actuar. • FilterType: Tipo de filtro de entre los que hemos definido previamente. Los combinaremos separándolos en comas. • ValidChars: sólo se le hará caso si hemos elegido a “Custom” como FilterType. Será un string con los caracteres que consideraremos válidos.

Ejemplo En nuestro ejemplo vamos a permitir que en nuestro TextBox se escriban únicamente números y los signos matemáticos ‘+’, ‘-‘, ‘*’ y ‘/’. <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <ajaxToolkit:FilteredTextBoxExtender ID="FilteredTextBoxExtender1" runat="server" TargetControlID="TextBox1" FilterType="Numbers,Custom" ValidChars="+-*/" > </ajaxToolkit:FilteredTextBoxExtender>

HoverMenu El HoverMenu es un extendedor aplicable a cualquier control Web. Vamos a distinguir entre el cuerpo y el popup, de modo que cuando el ratón pase sobre el control web cuerpo, el control web popup aparezca en el lugar en que hayamos especificado. Además, cuando esto suceda, podemos aplicar una clase CSS al control web cuerpo, haciendo ver al usuario que es el causante de que aparezca el popup.

Page 67: Teoria Ajax y Aspnet

AJAX y ASP.NET

67 Propiedades • TargetControlID: ID del control identificado como cuerpo. • PopupControlID: ID del control identificado como popup. • HoverCssClass: clase CSS que se aplicará al cuerpo cuando pasemos el ratón sobre éste. • PopupPostion: lugar donde aparecerá el popup con respecto al cuerpo. Por defecto vale Left, y sus otros valores son Right, Bottom y Center. • OffsetX/OffsetY: una vez definido el PopupPosition, podemos añadir o quitar pixels en horizontal o en vertical con respecto a su posición relativa. • PopDelay: la cantidad de milisegundos que pasarán entre que nos posemos sobre el cuerpo hasta que aparezca el popup. Por defecto son 100.

Ejemplo En nuestro ejemplo, el cuerpo se corresponde con un botón y el popup con un Panel, de modo que cuando el usuario vaya a hacer clic sobre el botón, se muestre un mensaje (Podemos asignarle cualquier propiedad al Panel): <asp:Button ID="Button1" runat="server" Text="Haz clic" /> <asp:Panel ID="Panel1" runat="server" Height="50px" Width="125px" BackColor="Yellow" BorderWidth="1px" ScrollBars="Auto"> Si presionas sobre el botón, se recargará la página. </asp:Panel> <ajaxToolkit:HoverMenuExtender ID="HoverMenuExtender1" runat="server" PopupControlID="Panel1" TargetControlID="Button1" PopupPosition="Right" OffsetX="10"> </ajaxToolkit:HoverMenuExtender>

ModalPopup El ModalPopup es otro ejemplo de potente funcionalidad en muy pocas líneas de código. Con éste, conseguimos el efecto de mostrar contenido deshabilitando la interacción con el resto de la página. Podemos emular el efecto del famoso “window.open(...)” de javascript sin necesidad de salir de la página en que estamos ni de abrir una nueva ventana del navegador. Imaginemos que el usuario presiona el botón “Dime tu nombre y apellidos”, de repente la página se oscurece y aparece en el centro un cuadro donde se pide el nombre y los apellidos... todo ello sin salir de la página en que estamos y sin poder hacer nada con el resto de elementos de ésta. Así pues, el usuario puede elegir entre cancelar -para volver donde estaba antes- y rellenar sus datos y presionar OK, activando una llamada a una función javascript que hayamos definido. Distinguiremos entre el activador, que en nuestro ejemplo es el botón “Dime tu nombre y apellidos”, y el popup, que en nuestro ejemplo se corresponde con el panel que nos mostrará el formulario de entrada de datos del usuario.

Page 68: Teoria Ajax y Aspnet

AJAX y ASP.NET

68 Propiedades • TargetControlID: ID del control activador. Típicamente será un Button o un LinkButton. • PopupControlID: ID del control popup. Típicamente será un Panel. • BackgroundCssClass: clase CSS que se aplicará al fondo de pantalla, por ejemplo para dar un efecto de oscuridad a los elementos sobre los que no vamos a poder interactuar. • DropShadow: le daremos el valor de true si queremos que se añada un efecto de sombra a nuestro control popup. • OkControlID: el ID del elemento que produce el efecto de OK de nuestro popup. • OnOkScript: nombre del script que se activará cuando presionemos sobre OK. • OkCancelID - The ID of the element that cancels the modal popup • OmCancelScript - Script to run when the modal popup is dismissed with the CancelControlID

Ejemplo En nuestro ejemplo, el activador será un Button que mostrará una ventana emergente (popup). Desde ésta actuaremos de forma diferente si presionamos sobre OK o sobre Cancel. En nuestro ejemplo hemos presionado OK <asp:Button ID="Button1" runat="server" Text="Abrir ventana emergente" /> <asp:Panel ID="Panel1" runat="server" Width="125px" BackColor="yellow"> Ventana emergente debida a la llamada del botón <br /> <asp:Button ID="Button2" runat="server" Text="OK" /> <asp:Button ID="Button3" runat="server" Text="Cancel" /> </asp:Panel> <ajaxToolkit:ModalPopupExtender ID="ModalPopupExtender1" runat="server" CancelControlID="Button3" OkControlID="Button2" OnCancelScript="Cancel()" OnOkScript="OK()" PopupControlID="Panel1" TargetControlID="Button1"> </ajaxToolkit:ModalPopupExtender> <script type="text/javascript"> function OK() { alert('Has apretado OK'); } function Cancel() { alert('Has apretado Cancel'); } </script>

Page 69: Teoria Ajax y Aspnet

AJAX y ASP.NET

69

NoBot El NoBot es un potentísimo control que nos ayudará a luchar contra el spam. Su funcionalidad trata de emular a los Captcha, de modo que se trata de evitar que un robot haga varios postback en la Web. Recordemos que los Captcha suelen ser imágenes de caracteres distorsionados sobre los que un humano tiene que evaluar qué caracteres son e introducirlos. Por tanto, un Captcha es mucho más seguro que un NoBot, pero el NoBot no requiere participación humana alguna, por lo que se hace transparente al usuario y le evita molestias. Así pues, podremos aplicar el NoBot sobre aplicaciones Web donde el Spam no sea un problema crítico, sino simplemente molesto.

Propiedades • OnGenerateChallengeAndResponse: método de servidor opcional desde donde podemos implementar un trabajo específico extra para ayudar al NoBot a detectar robots. Lo veremos mejor en el ejemplo. • ResponseMinimumDelaySeconds: número de segundos por debajo de los cuales un postback se considerará inválido.

Page 70: Teoria Ajax y Aspnet

AJAX y ASP.NET

70 • CutoffWindowSeconds: ventana de tiempo en segundos utilizada por el CutoffMaximumInstances. • CutoffMaximumInstances: cantidad de PostBacks permitidos por una misma IP en la ventana de tiempo definida por CutoffWindowSeconds.

Ejemplo Vamos a trabajar con el NoBot desde dos frentes. Por una parte no permitiremos que se hagan dos PostBacks en menos de 6 segundos (tiempo exagerado para hacer mejor la prueba. Por otro lado, mediante la función “CustomChagellengeResponse”, vamos a exigir que el navegador implemente el motor DOM, algo que sí hacen todos los navegadores modernos, pero no es común en Robots de Spam. La comprobación de si se ha pasado el Test la hacemos en el manejador del evento Load de la página, indicando –si procede- el motivo por el cual no se ha pasado la prueba. NoBot.aspx <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> <br /> <asp:Button ID="Button1" runat="server" Text="Button" /> <ajaxToolkit:NoBot ID="NoBot1" runat="server" ResponseMinimumDelaySeconds="6" OnGenerateChallengeAndResponse="CustomChallengeResponse" /> NoBot.aspx.cs protected void Page_Load(object sender, EventArgs e) { if (IsPostBack) { AjaxControlToolkit.NoBotState estado; if (!NoBot1.IsValid(out estado)) Label1.Text = "Eres un robot: " + estado.ToString(); else Label1.Text = "No eres un robot ;)"; } } protected void CustomChallengeResponse(object sender, AjaxControlToolkit.NoBotEventArgs e) { // Implicamos al motor DOM del navegador, exigiéndole unos sencillos calculos sobre el área de un Panel que nos inventamos Panel p = new Panel(); p.ID = "ParaMSCoder"; Random rand = new Random(); p.Width = rand.Next(300); p.Height = rand.Next(200); p.Style.Add(HtmlTextWriterStyle.Visibility, "hidden"); p.Style.Add(HtmlTextWriterStyle.Position, "absolute"); ((AjaxControlToolkit.NoBot)sender).Controls.Add(p); e.ChallengeScript = string.Format("var e = document.getElementById('{0}'); e.offsetWidth * e.offsetHeight;", p.ClientID);

Page 71: Teoria Ajax y Aspnet

AJAX y ASP.NET

71 e.RequiredResponse = (p.Width.Value * p.Height.Value).ToString(); }

NumericUpDown NumericUpDown extiende al control Web TextBox habilitando unos botones que incrementan/decrementan el valor de éste. El incremento/decremento puede corresponder a: - El simple +1/-1 aritmético. - Subir o bajar dentro de un listado de valores que le demos. - Llamar a un servicio Web o un método de la página diferente según si incrementamos o decrementamos. Podremos asignar botones para que hagan de incrementador/decrementador o dejar los que hay por defecto.

Propiedades • TargetControlID: ID del TextBox sobre el que vamos a actuar. • Width: anchura combinada del TextBox y sus botones de arriba/abajo que vienen dados por defecto (mínimo 25). Si elegimos que otros botones hagan esa función, está propiedad se ignorará. • RefValues: listado de valores sobre los que querremos ir subiendo y bajando. Los daremos en forma de string separado por punto y coma ‘;’. • TargetButtonDownID/TargetButtonUpID: ID de los botones que hará la función de incrementar y decrementar. • ServiceDownPath/ServiceUpPath: path del servicio Web al que llamaremos cuando se incremente o decremente. En caso de estar trabajando con métodos de página no utilizaremos esta propiedad. • ServiceDownMethod/ServiceUpMethod: método que será llamado para incrementar/decrementar el TextBox. Deberá tener la forma: [WebMethod] public int NextValue(int current, string tag) {…} • Tag: se corresponde con el segundo parámetro del método al que llamaríamos, y lo podemos utilizar para distinguir qué elemento está llamando al método.

Ejemplo En nuestro sencillo ejemplo, vamos a viajar por los planetas del sistema solar, donde ya no incluiremos a nuestro querido Plutón. <asp:TextBox ID="TextBox1" runat="server" Text="Tierra" Width="120" style="text-align:center"></asp:TextBox> <cc1:NumericUpDownExtender ID="NumericUpDownExtender1" runat="server TargetControlID="TextBox1" Width="120" RefValues="Mercurio;Venus;Tierra;Marte;Júpiter;Saturno;Urano;Neptuno" ServiceDownMethod="" ServiceUpMethod="" TargetButtonDownID="" TargetButtonUpID=""> </cc1:NumericUpDownExtender>

Page 72: Teoria Ajax y Aspnet

AJAX y ASP.NET

72 PasswordStrength El PasswordStrength es otro extendedor del TextBox. Con él podremos mostrar al usuario el nivel de fortaleza que tiene la contraseña que está escribiendo, en base a unos parámetros típicos de fortaleza que definiremos nosotros: - Número total de caracteres. - Exigencia de signos. - Exigencia de combinar mayúsculas y minúsculas. - Exigencia de números. Podemos elegir y configurar los dos modos que tenemos de mostrar al usuario la fortaleza de su password: - Mediante texto 100% configurable. - Mediante una barra que se irá rellenando. Además, podemos añadir la opción de “ayuda”, donde explicar al usuario cómo debe ser su contraseña.

Propiedades • TargetControlID: ID del TextBox sobre el que vamos a trabajar. • DisplayPosition: posición relativa del indicador con respecto al TextBox. Puede tomar 6 valores: AboveLeft, AboveRight, BelowLeft, BelowRight, LeftSide, RightSide. • StrengthIndicatorType: tipo de indicador: Text o BarIndicator. • PreferredPasswordLength: longitud mínima que debería tener la contraseña. • PrefixText: prefijo a mostrar cuando estemos mostrando el texto que describa la fortaleza de la contraseña. Típicamente será “Fortaleza= “. • TextCssClass: clase CSS que se aplicará al texto que describe la fortaleza de la contraseña. • MinimumNumericCharacters: cantidad mínima de caracteres numéricos. • MinimumSymbolCharacters: cantidad mínima de signos (ej.: $ ^ *) • RequiresUpperAndLowerCaseCharacters: especificamos si exigimos la combinación de mayúsculas y minúsculas. • TextStrengthDescriptions: listado de texto que se usará para describir la fortaleza de la contraseña. Irá ordenado de débil a fuerte y separado por punto y coma ‘;’. Tendrá un mínimo de 2 textos y un máximo de 10. Por ejemplo: “muy débil;débil;mejorable;buena;perfecta”. • CalculationWeightings: listado de 4 valores numéricos separados por ‘;’, donde la suma de ellos debe dar 100. Cada valor asigna un porcentaje de importancia a una característica del password; por ejemplo “40;25;15;20” significa que el 40% del peso de fortaleza viene de la longitud de la contraseña, el 25% a la cantidad de números, el 15% a mayúsculas/minúsculas y el 20% a la cantidad de caracteres no alfanuméricos. • BarBorderCssClass: Clase CSS del borde de la barra indicadora. • BarIndicatorCssClass: Clase CSS del interior de la barra indicadora. • HelpStatusLabelID: ID de la Label que usaremos –opcionalmente- para mostrar el texto de ayuda. • HelpHandleCssClass: clase CSS del elemento que mostrará el texto de ayuda. • HelpHandlePosition: posición relativa del elemento de ayuda con respecto al TextBox. Puede tomar 6 valores: AboveLeft, AboveRight, BelowLeft, BelowRight, LeftSide, RightSide.

Page 73: Teoria Ajax y Aspnet

AJAX y ASP.NET

73 Ejemplo Veamos qué fortaleza nos asigna este control: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <cc1:PasswordStrength ID="PasswordStrength1" runat="server" DisplayPosition="rightside" MinimumNumericCharacters="2" MinimumSymbolCharacters="2" PreferredPasswordLength="13" PrefixText="Fortaleza: " RequiresUpperAndLowerCaseCharacters="true" StrengthIndicatorType="Text" TargetControlID="TextBox1" TextStrengthDescriptions="muy débil; débil; mejorable; buena; perfecta"> </cc1:PasswordStrength>

PopupCOntrol El PopupControl se puede aplicar a cualquier control Web –al que llamaremos cuerpo- y su funcionalidad consiste en mostrar una pequeña ventana emergente con infomación adicional. Esa ventana emergente –a la que llamaremos popup- puede ser también cualquier control Web (típicamente un panel) y dentro de él podemos ubicar cualquier cosa. Por ejemplo, imagínese un TextBox en el que cuando se pone el ratón sobre él, emerja un calendario sobre el que podamos elegir una fecha y en el momento la elijamos, ésta se plasme en el TextBox.

Propiedades • TargetControlID: ID del control cuerpo. • PopupControlID: ID del control popup. • Position: posición relativa en la que aparecerá el popup con respecto al cuerpo. Sus valores

Page 74: Teoria Ajax y Aspnet

AJAX y ASP.NET

74 posibles serán: Left, Right, Top, Bottom, Center. • CommitProperty: especifica la propiedad del control cuerpo que se modificará con el resultado del popup. Por ejemplo, en el caso de un TextBox, lo normal es que queramos modificar su “value”, aunque también podríamos modificar su “Width”, su “TextMode”... Es opcional. • CommitScript: función javascript que se ejecutará cuando hayamos dado el resultado del popup. • OffsetX/OffsetY: distancia horizontal/vertical en pixels que añadiremos o quitaremos a la posición relativa del popup con respecto del cuerpo.

Ejemplo Aplicaremos el ejemplo propuesto en 3.15.1 PopUp.aspx Fecha: <asp:TextBox ID="TextBox1" runat="server" Width="80"></asp:TextBox> <asp:Panel ID="Panel1" runat="server" CssClass="popupControl"> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <center> <asp:Calendar ID="Calendar1" runat="server" BackColor="White" BorderColor="#999999" CellPadding="1" DayNameFormat="Shortest" Font-Names="Verdana" Font-Size="8pt" ForeColor="Black" Width="160px" OnSelectionChanged="Calendar1_SelectionChanged"> <SelectedDayStyle BackColor="#666666" Font-Bold="True" ForeColor="White" /> <TodayDayStyle BackColor="#CCCCCC" ForeColor="Black" /> <SelectorStyle BackColor="#CCCCCC" /> <WeekendDayStyle BackColor="#FFFFCC" /> <OtherMonthDayStyle ForeColor="#808080" /> <NextPrevStyle VerticalAlign="Bottom" /> <DayHeaderStyle BackColor="#CCCCCC" Font-Bold="True" Font-Size="7pt" /> <TitleStyle BackColor="#999999" BorderColor="Black" Font-Bold="True" /> </asp:Calendar> </center> </ContentTemplate> </asp:UpdatePanel> </asp:Panel> <ajaxToolkit:PopupControlExtender ID="PopupControlExtender1" runat="server" TargetControlID="TextBox1" PopupControlID="Panel1" Position="Bottom"> </ajaxToolkit:PopupControlExtender> PopupControl.aspx.cs protected void Calendar1_SelectionChanged(object sender, EventArgs e) { PopupControlExtender1.Commit(Calendar1.SelectedDate.ToShortDateString()); }

Page 75: Teoria Ajax y Aspnet

AJAX y ASP.NET

75 ResizableControl El ResizableControl extiende cualquier control Web (por ejemplo un Panel o una imagen) confiriéndole la propiedad de redimensionamiento. Podemos, por ejemplo, coger un Panel con texto y redimensionarlo a nuestro gusto sin más que cogerlo con el ratón. Además, añade multitud de funcionalidades, como lanzamiento de eventos “onresizing” y “onresize” con los que podemos crear lógica compleja. Su estado se mantiene durante los postbacks y sus dimensiones se pueden acceder desde cliente (javascript) y desde servidor (ASP.NET). También podemos limitar su anchura y altura máximas.

Propiedades • TargetControlID: ID del control Web que vamos a poder redimensionar. • HandleCssClass: clase CSS de elemento que debemos coger para redimensionar. • ResizableCssClass: clase CSS que se aplicará cuando estemos redimensionando. • MinimumWidth/MinimumHeight: anchura/altura mínimas. • MaximumWidth/MaximumHeight: anchura/altura máximas. • OnClientResize: evento que se lanzará cuando el elemento haya sido redimensionado • OnClientResizing: evento que se lanzará cuando el elemento esté siendo redimensionado. • HandleOffsetX/HandleOffsetY: offsets a aplicar sobre el elemento redimensionador.

Ejemplo <style> .handleText { width:16px; height:16px; background-image:url(images/HandleGrip.png); overflow:hidden; cursor:se-resize; } </style> <asp:Panel ID="Panel1" runat="server" Height="50px" Width="125px"> Elemento que se va a redimensionar </asp:Panel> <ajaxToolkit:ResizableControlExtender ID="ResizableControlExtender1" runat="server" MinimumWidth="50" MinimumHeight="20" MaximumWidth="250" MaximumHeight="125" HandleCssClass="handleText" TargetControlID="Panel1"> </ajaxToolkit:ResizableControlExtender>

RoundedCorners Aplica un redondeado de los bordes a cualquier control Web (habitualmente un Panel). Podemos elegir el radio de redondeo.

Page 76: Teoria Ajax y Aspnet

AJAX y ASP.NET

76 Propiedades • TargetControlID: ID del control Web sobre el que se aplicará el redondeo. Habitualmente es un Panel. • Radius: radio de redondeo de las esquinas. Por defecto vale 5. • Color: color de fondo del área redondeada en las esquinas. Por defecto se coge el color de fondo del Panel al que pertenece.

Ejemplo <asp:Panel ID="Panel1" runat="server" Width="125px" BackColor="#557755"> Este es el panel sobre el que se aplicará el bordeado. </asp:Panel> <ajaxToolkit:RoundedCornersExtender ID="RoundedCornersExtender1" runat="server" TargetControlID="Panel1" Radius="8"> </ajaxToolkit:RoundedCornersExtender>

Slider El Slider es un extendedor del TextBox, de modo que al aplicarlo sobre él, se convierte en un deslizador (ver ejemplo). Sus funcionalidades son múltiples. Por ejemplo se puede sincronizar con un TextBox o una Label, de modo que se va mostrando el valor numérico que representa. Podemos elegir un valor mínimo y un valor máximo, así como permitir números decimales. El movimiento del Slider puede ser contínuo o discreto (le marcaremos los pasos que debe dar). Además, soporta postbacks e incluso lo podemos combinar con un UpdatePanel para viajar al servidor en modo AJAX.

Propiedades • Minimum: Valor inferior. Por defecto es 0. • Maximum: Valor superior. Por defecto 100. • Decimals: Cantidad de decimales. Por defecto no hay. • Steps: Cuando queramos un deslizamiento discreto, marcaremos la cantidad de pasos. • Value: Valor actual del deslizador. • EnableHandleAnimation: Activa la animación. • HandleAnimationDuration: duración en milisegundos de la animación. • RailCssClass: Asigna una clase CSS a la vía sobre la que se mueve el deslizador. • HandleCssClass: Asigna una clase CSS al deslizador.

Page 77: Teoria Ajax y Aspnet

AJAX y ASP.NET

77 • HandleImageURL: opcionalmente podemos asignar una imagen al deslizador. • Length: Longitud del deslizador. Por defecto se cogerá la longitud del TextBox que estamos extendiendo • BoundControlID: ID del TextBox o Label en el que estamos mostrando el valor del deslizador. • RaiseChangeOnlyOnMouseUp: Si se activa, lanza el evento “change” cuando se suelta el botón izquierdo del ratón.

Ejemplo Mostramos lo fácil que es crear un Slider. <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> <ajaxToolkit:SliderExtender ID="SliderExtender1" runat="server" TargetControlID="TextBox1" BoundControlID="TextBox2" />

TextBoxWatermark El TextBoxWatemark extiende, de nuevo, al control TextBox. Su funcionalidad consiste en que aparezca un texto (de una clase CSS específica) en el TextBox cuando este no haya sido rellenado por el usuari, de modo que cuando hagamos clic sobre éste, ese texto desaparezca, y si nos vamos del textbox sin haber escrito nada, el texto vuelve a aparecer. Su finalidad habitual es la de mostrar al usuario cierta información antes de rellenar el TextBox.

Propiedades • TargetControlID: ID del TextBox que vamos a extender. • WatermarkText: Texto que se mostrará cuando no haya nada escrito en el TextBox. • WatermarkCssClass: la clase CSS que se aplicará al TextBox cuando no haya nada escrito.

Ejemplo Vamos a pedir el nombre de usuario y contraseña. En la primera imagen vemos cómo quedarán los cuadros de texto nada más cargarse la página; en la segunda imagen hemos hecho click sobre el primer TextBox y de inmediato se ha borrado el texto “Nombre de usuario” para dejarnos escribir lo que queramos. <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <br /> <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox> <ajaxToolkit:TextBoxWatermarkExtender ID="TextBoxWatermarkExtender1" runat="server" TargetControlID="TextBox1" WatermarkText="Nombre de usuario" /> <ajaxToolkit:TextBoxWatermarkExtender ID="TextBoxWatermarkExtender2" runat="server" TargetControlID="TextBox2" WatermarkText="Contraseña" />

Page 78: Teoria Ajax y Aspnet

AJAX y ASP.NET

78

ToggleButtn El ToggleButton extiende al control CheckBox. Su única funcionalidad consiste en sustituir por imágenes el estado de un CheckBox. Es decir, si el CheckBox está “checked” mostrar una imagen específica, y su está “unchecked” mostrar otra.

Propiedades • TargetControlID: ID del CheckBox que extenderemos. • CheckedImageUrl: URL de la imagen a mostrar cuando el CheckBox esté “Checked”. • UncheckedImageUrl: URL de la imagen a mostrar cuando el CheckBox esté “UnChecked”. • DisabledCheckedImageUrl: URL de la imagen a mostrar cuando el CheckBox está deshabilitado y en estedo de “Checked”. • DisabledUncheckedImageUrl: URL de la imagen a mostrar cuando el CheckBox está deshabilitado y en estedo de “UnChecked”. • CheckedImageAlternateText: texto alternativo de la imagen definida en CheckedImageUrl. • UncheckedImageAlternateText: texto alternativo de la imagen definida en UnCheckedImageUrl. • ImageHeight/ImageWidth: Altura/Anchura de la imagen que se va a mostrar.

Ejemplo <asp:CheckBox ID="CheckBox1" Checked="true" Text="Mi CheckBox" runat="server"/> <br> <ajaxToolkit:ToggleButtonExtender ID="ToggleButtonExtender1" runat="server" TargetControlID="CheckBox1" ="No seleccionado" />

ValidatorCallout El ValidatorCallout es un extendedor de cualquier tipo de validador (RequiredFieldValidator, RangeValidator, CustomValidator...), con el que conseguimos una vista mucho más amable de los típicos validadores. No tenemos que aplicar los validadores como lo hemos hecho hasta ahora (ver http://www.subgurim.net/articulos/asp-net-general-articulo48.aspx), pero con el detalle de añadirles el atributo Display=”None” y asignarles el ValidatorCallout.

Propiedades • TargetControlID: ID del Validador que se está extendiendo. • Width: Anchura del Callout • HighlightCssClass: Opcionalmente se puede asignar una clase CSS sobre el Callout.

Page 79: Teoria Ajax y Aspnet

AJAX y ASP.NET

79 • WarningIconImageUrl: Url del icono que muestra la alerta. Si no se especifica se muestra el que viene por defecto. • CloseImageUrl: Imagen que produce el cierre del Callout

Ejemplo Un ejemplo vale más que mil palabras, y en casos como el Callout mucho más: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" Display="None" ErrorMessage='Mensaje de error donde podemos añadir todo tipo de HTML, por ejemplo una <a href="http://www.es-asp.net">Url cualquiera</a>.' ControlToValidate="TextBox1"></asp:RequiredFieldValidator> <br /> <asp:Button ID="Button1" runat="server" Text="Button" /> <ajaxToolkit:ValidatorCalloutExtender runat="Server" ID="ValidatorCalloutExtender1" TargetControlID="RequiredFieldValidator1" Width="350px" />