Gestión de una aplicación completa con .NET Servicio de Informática TEMA 9: Controles dinámicos y objetos persistentes Objetos persistentes........................................................................................................................1 Introducción.................................................................................................................................1 Serialización de clases................................................................................................................2 Asignación y lectura de ViewState...............................................................................................3 Variables de sesión y aplicación..................................................................................................4 Cambiar la ubicación de almacenamiento...................................................................................4 Controles dinámicos........................................................................................................................5 Agregar controles dinámicamente a un formulario.......................................................................5 Propiedades más comunes......................................................................................................5 Paneles........................................................................................................................................6 Cajas de Texto............................................................................................................................6 Etiquetas......................................................................................................................................6 Botones y gestión de eventos......................................................................................................7 Controles en una página..............................................................................................................7 Objetos persistentes Introducción Por necesidades de una aplicación nos puede interesar mantener un objeto con los mismos datos entre diferentes envíos de datos (postbacks).. Por ejemplo supongamos que tenemos un objeto ClaseAlumnos sobre el que realizamos numerosas operaciones en distintas páginas de nuestra aplicación web y damos la opción al usuario de guardar esos cambios en la base de datos en cualquier momento mediante un botón de guardar. Nos sería de gran utilidad mantener una instancia de ClaseAlumnos que se mantenga durante todo el proceso hasta que el usuario decidiese almacenar sus datos en la base de datos (o rechazar los cambios). De esta forma sólo accederíamos a la base de datos al principio, para cargar los datos y al final, para guardarlos, manteniendo todos los datos almacenados en la instancia, sin preocuparnos de crear campos ocultos para ir pasando los datos de una página a otra. Cargar Datos personales.aspx expediente.aspx economicos.aspx Modificar Datos personales Modificar Datos Expediente Modificar Datos Económicos alumnoActual = new ClaseAlumno(id); alumnoActual.Carga(); Tema 9 / Página 1 Guardar Datos alumnoActual.Guarda(); Gestión de una aplicación completa con .NET Servicio de Informática Las páginas web de ASP.NET tiene una técnica para mantener los cambios de estado entre envíos de datos, llamado Viewstate. Viewstate almacena el estado de los controles de un formulario web para poder recuperarlos después de un reenvío. Por defecto en un campo oculto del formulario llamado _VIEWSTATE. Podemos aprovecharnos de esta característica para almacenar nuestros objetos en el viewstate y recuperarlos después de un envío de datos. Serialización de clases Para poder poder pasar un objeto de un envío a otro se necesita que el objeto sea transformable en una cadena de texto. Esto se hace mediante la directiva Serializable que pondremos antes de la declaración de la clase. Por ejemplo en nuestra clase de alumno pondríamos: [Serializable] public class ClaseAlumno { private int _numeroExpediente; private int _nombre; ... Si una clase tiene como variables miembro otras clases estas también tienen que ser serializables. Por ejemplo si la clase de alumno tuviese una variable miembro del tipo clase expediente: [Serializable] public class ClaseAlumno { private int _numeroExpediente; private int _nombre; private ClaseExpediente _expediente; ... Tendríamos que modificar también está última [Serializable] public class ClaseExpediente { int _codigoEstudio; Ahora ya se puede transformar las instancias de la clase en una cadena de texto para ser enviado de página a página. Tema 9 / Página 2 Gestión de una aplicación completa con .NET Servicio de Informática Si intentamos guardar en ViewState un objeto de una clase que no está marcada como serializable obtendremos el error: El tipo 'NombreDeLaClase' del ensamblado 'App_Code.axi01zgc, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' no está marcado como serializable Asignación y lectura de ViewState Para almacenar un objeto en el ViewState simplemente le asignamos una clave y lo agregamos con: ViewState["elAlumno"] = elAlumno; y para leerlo realizaremos la operación contraria pero añadiendo conversión de tipos elAlumno = (ClaseAlumno) ViewState["elAlumno"];: Ejemplo, nos guardamos un objeto alumno en viewstate y lo leemos si hay envío de datos ClaseAlumno elAlumno; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { elAlumno = new ClaseAlumno(); elAlumno.Nombre = "Pepe"; elAlumno.Apellidos = "García López"; ViewState["elAlumno"] = elAlumno; Consola.Text = "<br />" + elAlumno.Nombre + " " + elAlumno.Apellidos + " guardado en View State"; } else { elAlumno = (ClaseAlumno) ViewState["elAlumno"]; Consola.Text = "<br />" + elAlumno.Nombre + " " + elAlumno.Apellidos + " leído de View State"; } } Tema 9 / Página 3 Gestión de una aplicación completa con .NET Servicio de Informática Variables de sesión y aplicación Podemos almacenar objetos en variables de sesión y aplicación aunque estos no estén etiquetados como serializables. Guardar un objeto Session["laAlumna"] = laAlumna; Recuperarlo laAlumna = (ClaseAlumno)Session["laAlumna"]; Cambiar la ubicación de almacenamiento Podemos alterar nuestra aplicación para que el estado de los controles (ViewState) se almacene en el estado de la sesión en vez de en un campo oculto de la página. Para ello sobrescribimos la propiedad PageStatePersister de la siguiente forma: protected override PageStatePersister PageStatePersister { get { return new SessionPageStatePersister(this); } } Tema 9 / Página 4 Gestión de una aplicación completa con .NET Servicio de Informática Controles dinámicos Puede ser que a priori no conozcamos los controles que vamos a mostrar en una página, que estos dependan por ejemplo de ciertos valores que tenemos en una base de datos y que cambian en distintas ejecuciones de la página. Por ejemplo si mostramos un formulario para modificar los datos de un alumno y sus estudios. Hasta que no sepamos el alumno que vamos a modificar no sabremos cuantos ni que estudios tiene por lo que los controles de la página tendrán que generarse “al vuelo”. Agregar controles dinámicamente a un formulario Para agregar controles a un formulario necesitaremos un panel o cualquier otro contenedor para insertarlos. El mecanismo será siempre el mismo: creación del control, asignarle valores y agregarlo a la lista de controles del contenedor. Control miControl = new Control(); miControl.Propiedad = "Valor"; Contenedor.Controls.Add(miControl); Propiedades más comunes A continuación se muestran algunos de las propiedades más comunes que se aplican a los controles AutoPostBack Indica si se produce una devolución automática de datos cuando el control cabia ClientID Identificador del control de servidor generado por .NET CssClass Estilo que se le va a aplicar al control Enabled Establece si esta habilitado o no EnableViewState Indica si tiene que mantener su valor entre reenvíos ID Obtiene o establece el identificador de programación Page Obtiene una referencia a la página que contiene el control Parent Obtiene una referencia al control que contiene al actual Tema 9 / Página 5 Gestión de una aplicación completa con .NET Servicio de Informática ReadOnly Obtiene o establece si el control es de sólo lectura SkinID Identificador del skin para el control Text Contenido del control Visible Obtiene o establece si el control es visible o no Paneles Utilizaremos los paneles como contenedores de otros controles Panel Datos = new Panel(); Datos.ID = "DatosAlumno"; Datos.CssClass = "panelDatos"; Contenedor.Controls.Add(Datos); El código de cliente que me generaría sería simplemente: <div id="DatosAlumno" class="panelDatos"> </div> Cajas de Texto Para que el usuario introduzca datos TextBox textBoxTitulo = new TextBox(); textBoxTitulo.ID = "TextBoxTitulo"; textBoxTitulo.Text = "Pon el titulo"; Datos.Controls.Add(textBoxTitulo); Etiquetas Para poner bloques de texto en los formularios. Podemos asociarlas a otro control. Label titulo = new Label(); titulo.Text = "Titulo"; titulo.AssociatedControlID = "TextBoxTitulo"; Datos.Controls.Add(titulo); Como se puede observar en los ejemplos estamos añadiendo los controles al primer control creado, el panel Datos, que a su vez es un control del panel Contenedor. Tema 9 / Página 6 Gestión de una aplicación completa con .NET Servicio de Informática Botones y gestión de eventos Podemos crear dinámicamente controles que generen eventos como los botones Para gestionar los eventos agregaremos un gestor de eventos al evento que queramos tratar de la forma: nombreControl.Evento += new EventHandler(MetodoAejecutar); Luego nos tendremos que crear el método que trata el evento: void MetodoAejecutar(object sender, EventArgs e) { // Bla bla bla } Un ejemplo con un botón sería: Button botonAceptar = new Button(); botonAceptar.Text = "Aceptar"; botonAceptar.CausesValidation = false; botonAceptar.Click += new EventHandler(botonAceptar_Click); Datos.Controls.Add(botonAceptar); y el gestor void botonAceptar_Click(object sender, EventArgs e) { // Gestionar evento } Controles en una página Podemos recorrer todos los controles que hay en una página o en otro control mediante la colección Controls. Por ejemplo si queremos saber el identificador de los controles contenidos en el Panel Datos: foreach (Control elControl in Datos.Controls) { } Label1.Text +="<br />Control: " + elControl.ID; Si queremos saber si un control contiene otros utilizaremos el método HasControls if (Datos.HasControls()) Tema 9 / Página 7 Gestión de una aplicación completa con .NET Servicio de Informática Para buscar un control en una página o en otro control se utiliza el método FindControl. Este método recibe como parámetro el identificador del control y devuelve el control. Busca en toda la jerarquía de controles: TextBox elTextBox = (TextBox) Page.FindControl("TextuuuBoxTitulo"); Tema 9 / Página 8