Introducción
Cuando se desarrolla pantallas de captura de datos por lo general una característica deseable implica que no se pierda los datos cargados cuando se navega a otro sitio a buscar información y se vuelve.
Lamentablemente asp.net no conserva de forma automática el estado de esta información ingresada, por esa razón seremos nosotros quienes mediante código que volquemos la info ingresada para no perderla y facilitar al usuario al operación con la aplicación.
En el ejemplo planteado se cuenta con una lista de productos, con la posibilidad de ingresa una cantidad y opciones provistas para completar la operación.
Mantener el estado de los datos ingresados
Si bien esta funcionalidad es muy similar a la implementada para mantener el estado de los check, cuenta con algunas diferencias que hay que remarcar.
En este caso se conserva algo mas de información que una simple estado de true/false, es por eso que se crea una clase para mantener los datos que son útiles.
internal class ProductInfo
{
public int Id { get; set; }
public int Amount { get; set; }
public int Shipper { get; set; }
}
Es desde y hacia esta clase que se realizaran las conversiones.
El mantener la información consta de varios pasos:
- se recuperan del gridview solo aquellas rows en donde se ingresara una cantidad y un medio de envió. Se arma en este caso una entidad ProductInfo representativa de los datos que se quiere conservar
- se recupera la información previamente registrada en la session
- se cruzan las listas para quitar las que están en la pagina actual
- se ingresa la nueva información para conservar en session
public static void KeepProductInfo(GridView grid)
{
//
// se obtienen la lista de producto con informacion proporcionada por el usuario
//
var listProd = from item in grid.Rows.Cast<GridViewRow>()
let amount = ((TextBox)item.FindControl("txtAmount")).Text
let shipper = ((DropDownList)item.FindControl("ddlShippers")).SelectedValue
where !(string.IsNullOrEmpty(amount) || shipper == "0")
select new ProductInfo()
{
Id = Convert.ToInt32(grid.DataKeys[item.RowIndex].Value),
Amount= Convert.ToInt32(amount),
Shipper = Convert.ToInt32(shipper)
};
//
// se recupera de session la lista de seleccionados previamente
//
List<ProductInfo> prodInfo = HttpContext.Current.Session["ProdInfo"] as List<ProductInfo>;
if (prodInfo == null)
prodInfo = new List<ProductInfo>();
//
// se cruzan todos los ingresados en la pagina actual, con los previamente conservados
// en Session, devolviendo solo aquellos donde no hay coincidencia
//
prodInfo = (from item in prodInfo
join item2 in listProd
on item.Id equals item2.Id into g
where !g.Any()
select item).ToList();
//
// se agregan la actualizacion realizada por el usuario
//
prodInfo.AddRange(listProd);
HttpContext.Current.Session["ProdInfo"] = prodInfo;
}
Por supuesto esta misma técnica puede ser usada para conservar cualquier tipo de dato de cualquier pantalla quiere se quiera evitar perder lo ingresado, se podría haber mantenido la info de textbox simple, o de un checkboxlist, combos, etc.
En este caso se uso un gridview porque es un objeto representativo de información compleja para procesar.
Recuperar la info de los datos conservados en session
La acción de recuperar se podría resumir en tres paso
- recuperar la información de session
- cruzar las row del gridview de la pagina actual con la lista de productos existente
- volcar las coincidencias en los controles textbox y dropdownlist
public static void RestoreProductInfo(GridView grid)
{
List<ProductInfo> prodInfo = HttpContext.Current.Session["ProdInfo"] as List<ProductInfo>;
if (prodInfo == null)
return;
//
// se comparan los registros de la pagina del grid con los recuperados de la Session
// los coincidentes se devuelven para ser seleccionados
//
var result = (from item in grid.Rows.Cast<GridViewRow>()
join item2 in prodInfo
on Convert.ToInt32(grid.DataKeys[item.RowIndex].Value) equals item2.Id into g
where g.Any()
select new
{
gridrow = item,
prodonfo = g.First()
}).ToList();
//
// se recorre cada item para asignar la informacion
//
result.ForEach(x =>
{
((TextBox)x.gridrow.FindControl("txtAmount")).Text = Convert.ToString(x.prodonfo.Amount);
((DropDownList)x.gridrow.FindControl("ddlShippers")).SelectedValue = Convert.ToString(x.prodonfo.Shipper);
});
}
Uso de la funcionalidad implementada
Si bien al momento de conservar los datos ante un paginado se contaba con eventos concretos pre y post para llevar la acción de conservar o recuperar los datos, en este caso también se deberá hallar momentos equivalentes para los cuales volcar los datos.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadGridProducts();
//
// lusgo de cargar el grid se asigna la info que el usuario habia ingresado
//
ProductsManager.RestoreProductInfo(gvProducts);
}
}
private void LoadGridProducts()
{
gvProducts.DataSource = NorthwindData.GetAllProducts();
gvProducts.DataBind();
}
protected void gvProducts_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
//
// se persiste la informacion ingresada por el usuario
//
ProductsManager.KeepProductInfo((GridView)sender);
//
// se recupera el producto seleccionado
//
int productId= Convert.ToInt32(gvProducts.DataKeys[e.NewSelectedIndex].Value);
Response.Redirect(string.Format("ProductDetails.aspx?productId={0}", productId));
}
Tanto en la carga del formulario, como al momento de seleccionar unos de los ítems del grid es que se invocaran la funcionalidad que interactúa con el medio que conserva los datos
Código
El ejemplo ha sido implementado con VS2008 y hace uso de una base de datos Sql Compact
[C#]
|
[C# Skydrive]
|



16 comentarios:
Hola, nuevamente yo por acá, una preguntica, sólo mantienes información de la última página visitada? o mantienes todas las páginas visitadas?
Gracias.
hola Pierina Joplin
puedes manter informacion de las paginas que quieras y sientas que aporta valor mantener estado, digo tampoco mantener estado de todo tendria sentido, pero donde la operacion del ir y volver es importante alli aplica
en este caso esa clase Manager solo mantiene el de esa pagian en concreto
pero si quieres mantener el de otras solo es cuestion de crearle su manager y eso es todo (aplciando esta misma tecnica)
la informacion dentro del manager puede ser tan compleja como lo necesite, solo sera cuestion de modelar la entidad que guardas en la Session
saludos
Gracias.. Aunque no quede muy convencida.. :)
Hola, he leido tus respuestas en foro de MSDN y veo que sabes bastante, yo publique uno recientemente no hayo que hacer, agradeceria mucho tus opiniones
http://social.msdn.microsoft.com/Forums/es-ES/netfxwebes/thread/f4261091-d4e4-4a2d-8f7a-d8fc918a478e/#f4261091-d4e4-4a2d-8f7a-d8fc918a478e
hola xxx
he dado la respuesta en el foro, has probado lo que comento
saludos
Si Leando recien lo lei, ya conteste, gracias por el interes
Una pregunta con respecto a las variables estáticas, en un principio esa solución me pareció práctica pero el problema me resultó que cuando mas de un usuario accedia a un Formulario con un grid X que se cargaba con los datos de estáticos, se mostraban en la computadora A y B lo que estaba visualizando la computadora C o en su defecto al inicializarla por la computadora A o B la computadora C perdia su información. No se si estaré haciendo algo mal o qué. Mi solución fue utilizar variables de sesión para no usar estas variables estáticas. Salu2 desde Ecuador
hola Carlos Misael
efectivamente definir una variable como static implica que esta actuara como el objeto Application de asp.net, o sea sera visible para el sitio completo y todos los usuario compatiran la misma info del mismo
es por eso que si se quiere tener dato concretos por usuario se usa el objeto Session
saludos
Hola Leandro, tengo una aplicación en asp.net y utilizo variables de sesión pero después de cierto tiempo que deja la pagina abierta se pierde y marca error, para recuperar la información de las variables debo enviarlas a textos y después recuperarlas (session("variable")=me.textbox1.text)?
hola HugoSoft
eso es comun que suceda, las session tienen un tiempo de expiracion, el valor por defecto son 20 min, si durante este tiempo no realizaste ninguna accion que implique ir al servidor, la session se pierde
deberias agregar validaciones para en caso de perder la seccion no falle la informacion que recuperas
saludos
Hola Leandro, el codigo esta muy bueno, pero tengo un problema que no consigo subsanar
Tengo un area de carga de datos para el gridview, el cual posee un boton de consulta de articulos, cuando hago clic al bonton consulta de articulos me redirige a otra pagina, cuando vuelvo me trae los datos del articulo y los inserto en la grilla ingresando la cantidad y precio
El problema es que no puedo aplicar tu codigo para mantener los datos ya ingresados a la grilla
Agradeceria que me ayudes u orientes un poco en este caso
hola Darkkatt
no evaluaste en lugar de hacer un redirect a otra pagina para realizar la seleccion usar mejor un popup ?
[ASP.NET] PopUp Edición - Usando Jquery UI Dialog
no he implementado directo para completar campos pero la tecncia no deberia cambiar mucho
con un popup evitarias perder la edicion del grid
saludos
Leandro, tendrías una versión de tu código pero para VB gracias
hola
la verdad no lo he implementado en vb.net
aunque podrias ver de ayudarte con tool como estas
Convert c#
saludos
Hola Leandro,
era lo que estaba buscando pero me he dado cuenta de que si una vez tengo datos en la primera y segunda página si me voy a la primera y quito algún dato al volver a esa página me vuelve a poner el dato que he quitado.
Que debería hacer?
Un saludo,
hola Encarni
cuando cambias entre las paginas es que se realiza la operacion de volcado de los registros marcados, podrias poner en ese evento un breakpoint y evaluar si puntualmente se esta realziando esa actualizacion, y sino es que se conservan los datos marcados previamente
verifica puntualmente donde se cruzan los datos usando linq y que esto sea efectivo
pero para esto solo es cuestion de un breakpoint y ver que resuelve los datos inspeccionado las variables
saludos
Publicar un comentario en la entrada