jueves, 29 de abril de 2010

Congelar cabeceras gridview

Después de mucho buscar soluciones bastantes más complejas que esta y ver que realmente no acababan de afinar del todo, encontré esta solución que no consiste nada más que en mostrar una capa con una tabla donde debería estar el header del gridview y que funciona perfectamente.

La solución la podemos encontrar en la siguiente web:

Abrir un popup desde los atributos de una imagen

Simplemente hay que hacer lo siguiente:

imgbAyuda.Attributes.Add("onclick", "window.open('AcercaDe.aspx' ,'QTest' , 'width=477,height=300,top=200,left=440,toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no')");

Dándoles los valores que deseemos...

Centrar la paginación de un gridview

Muchas veces no conseguimos que la puta paginación del gridview se centre a través del propio código del pagerstyle. Para conseguir centrarlo se puede usar wel siguiente código

protected void gvCampos_OnPreRender(object sender, EventArgs e)
{
base.OnPreRender(e);
GridViewRow pagerRow = gvCampos.BottomPagerRow;
if (pagerRow != null) pagerRow.Cells[0].Attributes.Add("align", "center");
}

Lanzamos el evento onPreRender y listo.

martes, 27 de abril de 2010

Mantener el estado de un treeview entre distintas páginas navegadas

Para eso debemos añadir un fichero de clase con el siguiente código:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI.WebControls;

public class TreeViewState
{
public void SaveTreeView(TreeView treeView, string key)
{
List list = new List();
SaveTreeViewExpandedState(treeView.Nodes, list);
HttpContext.Current.Session[key + treeView.ID] = list;
}

private void SaveTreeViewExpandedState(TreeNodeCollection nodes, List list)
{
foreach (TreeNode node in nodes)
{
list.Add(node.Expanded);
if (node.ChildNodes.Count > 0)
{
SaveTreeViewExpandedState(node.ChildNodes, list);
}
}
}

private int RestoreTreeViewIndex;

public void RestoreTreeView(TreeView treeView, string key)
{
RestoreTreeViewIndex = 0;
RestoreTreeViewExpandedState(treeView.Nodes,
(List)HttpContext.Current.Session[key + treeView.ID] ?? new List());
}

private void RestoreTreeViewExpandedState(TreeNodeCollection nodes, List list)
{
foreach (TreeNode node in nodes)
{
if (RestoreTreeViewIndex >= list.Count) return;

node.Expanded = list[RestoreTreeViewIndex++];
if (node.ChildNodes.Count > 0)
{
RestoreTreeViewExpandedState(node.ChildNodes, list);
}
}
}
}


Una vez creada esta clase debemos incluir en la página o en el control de usuario el siguiente código.
En el load del arbol, una vez hayamos recuperado todos los elementos y generado la estructura del arbol ponemos la siguiente línea:

new TreeViewState().RestoreTreeView(arbol, this.GetType().ToString());

Y además de esto añadimos un evento Unload a nuestro arbol para que guarde el estado actual al cambiar de página.

protected void arbol_Unload(object sender, EventArgs e)
{
// save the state of all nodes.
new TreeViewState().SaveTreeView(arbol, this.GetType().ToString());
}

Y con esto ya se mantendrá perfectamente la estructura de3 nuestro TreeView entre las distintas páginas de nuestra aplicación.

Guardar un fichero en SQL Server

Yo no sabía que se podía hacer, pero esto es lo mejor de tener compañeros k saben mazo. El procedimiento es el siguiente:

Creamos dentro de la tabla correspondiente un campo varbinary(max) que alojará nuestro fichero. Dentro de un formulario metemos un FileUpload que capturé el fichero a subir y un botón que será el que capturé el evento de guardarlo.

Bien en el codebehind del botón ponemos lo siguiente:

if (FileUpload1.HasFile)
{
//Creamos un array de bytes para almacenar los datos leídos por fs.
Byte[] data = FileUpload1.FileBytes;
//Y guardamos los datos en el array data
Incidencias.Incidencia.fichero = data;
}

Esto está por LINQ to SQL pero por ADO.NET sería exactamente igual, se lo pasaríamos como un parámetro más a la inserción y listo.

En el momento de querer descargar el fichero, los pasos a seguir son los siguientes. Metemos en el formulario un botón descargar y en la parte de código lo siguiente:


protected void btnDescargar_Click(object sender, ImageClickEventArgs e)
{
try
{
IncidencyManager Incidencias = new IncidencyManager(int.Parse(idPruebaGuardar));

Response.ClearContent();
Response.ClearHeaders();
Response.Buffer = true;
Response.ContentType = "text/plain";
Response.AddHeader("Content-Disposition", "attachment; filename=" + txtFichero.Text);
Response.BinaryWrite(Incidencias.Incidencia.fichero.ToArray());
Response.Flush();
Response.Close();
}
catch (Exception ex)
{
}
}

Lo mismo, está en LINQ pero sino en al BinaryWrite le pasaís el parametro correspondiente y perfecto. Dejar el catch sin nada porque en el caso de querer cancelar el usuario la descarga, se produce una excepción, pero que en mi opinión no se debería de capturar.

Rollover sobre una imagen

Para lograrlo basta con escribir el siguiente código:

imgbLogout.Attributes.Add("onmouseover", "this.src='Images/img-b_10.png'");
imgbLogout.Attributes.Add("onmouseout", "this.src='Images/img_10.png'");

Declaración de variables por sesión de una forma limpia y sin fallos

Todos hemos tenido los típicos fallos cuando vas a intentar asignar una variable por sesión y esta tiene un valor null y te salta una excepción.
Bien, ese fallo se puede controlar declarando las variables de la siguiente forma:

public int idProyecto
{
get { return (Session["idProyecto"] == null ? 0 : (int)Session["idProyecto"]); }
set { Session["idProyecto"] = value; }
}

public string NombreFichero
{
get { return (Session["NombreFichero"].ToString() == String.Empty ? String.Empty : Session["NombreFichero"].ToString()); }
set { Session["NombreFichero"] = value; }
}

Sin fallos en una demo de una aplicación Web

A veces hay que presentar una demo de un web en un cliente, y puede que ese producto no esté acabado del todo, por lo que pueden surgir bastantes fallos sin controlar que nos lleven al típico pantallazo de excepción no controlada.

Para solucionar esto podemos usar el siguiente código:

void Application_Error(object sender, EventArgs e)
{
Context.Server.ClearError();
Response.Redirect(Request.RawUrl);
}

Generamos un fichero global.asax y en la zona de Application_Error introducimos el siguiente código, que lo que hará será eliminar los errores y volver a recargar nuestra página como si nada hubiese fallado.
Desde luego k no es la mejor solución pero a veces el tiempo aprieta....

Añadir evento onclick sobre las celdas de un gridview

Para añadir un evento onclick a las celdas de un gridview nos podría valer este código k se muestra a continuación.

void gvEjecuciones_RowDataBound(object sender, GridViewRowEventArgs e)
{
try
{
foreach (GridViewRow row in gvEjecuciones.Rows)
{
TextBox txtTipoEstado = (TextBox)row.FindControl("txtEstado");
Image imgTipoEstado = (Image)row.FindControl("imgEstado");
// Si es una fila de datos
if (e.Row.RowType == DataControlRowType.DataRow)
{
// añade al evento onclick la acción de RowComman seleccionar con el valor del control del tipo label llamado lblID
e.Row.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference((GridView)sender, "Seleccionar$" + ((Label)(e.Row.FindControl("lblIdPrueba"))).Text));
e.Row.Style.Add("cursor", "hand");

if (((TextBox)(e.Row.FindControl("txtCodGrupoPruebas"))).Text == codGrupoPruebas.ToString())
{
e.Row.Attributes.Add("Style", "background-image: url(Images/img_35.png);");
}
}
}
}

Este método hace dos cosas, genera un evento onclick y captura la fila pulsada previamente y le pone una imagen como background

Para controlar el onclick solo habría k capturar el rowcommand, algo así:

protected void gvEjecuciones_RowCommand(object sender, GridViewCommandEventArgs e)
{
try
{
Filtrar();
switch (e.CommandName)
{
case "Seleccionar":
codGrupoPruebas = int.Parse(e.CommandArgument.ToString());
cargarGrid();
Filtrar();
break;
}
}
catch (Exception ex)
{
Response.Redirect("Error.aspx?Mensaje=" + ex.Message.Replace("\n", " "));
}
}

Paginación sobre un gridview

Para conseguir un paginación rápida y fácil sobre los elementos de un gridview podemos usar el siguiente código:
Creamos un grid con AllowPaging true y con el pagesize que queramos, y le añadimos los eventos onpageindexchanging and onpageindexchanged.

AllowPaging="True" onpageindexchanged="gvEjecuciones_PageIndexChanged"
onpageindexchanging="gvSolicitudes_PageIndexChanging">

Después en el codebehind capturamos esos eventos con el siguiente código

protected void gvEjecuciones_PageIndexChanged(object sender, EventArgs e)
{
this.gvEjecuciones.SelectedIndex = ((this.gvEjecuciones.PageIndex + 1)
* this.gvEjecuciones.PageSize);
}


protected void gvSolicitudes_PageIndexChanging(object sender , GridViewPageEventArgs e)
{
GridView gv = ((GridView)(sender));
int pagina = e.NewPageIndex;

if (pagina >= 0)
{
gv.PageIndex = pagina;
}
cargarGrid(); ((método que rellena el gridview con datos))
}
}

Con esto conseguiremos la paginación sobre nuestro gridview

Ventanita cargando AJAX

Para hacer que salga la típica ventanita con un gif animado de AJAX, el código es el siguiente:

Dentro del css:

.AlertModalBackground
{
background-color: #FFFFFF;
filter: alpha(opacity=70);
opacity: 0.2;
height: 20%;
widows: 100%;
}
.modalBackground
{
background-color: white;
filter: alpha(opacity=20);
opacity: 0.2;
}

<script type="text/javascript" language="javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(initializeRequest);
prm.add_endRequest(endRequest);
function initializeRequest(sender, args) {
document.body.style.cursor =
"wait";
if (prm.get_isInAsyncPostBack()) {
//debugger
args.set_cancel(true);
}
}
function endRequest(sender, args) {
document.body.style.cursor =
"default";
}
//JavaScript code included at jsUpdateProgress.js file
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginReq);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endReq);
function beginReq(sender, args) {
// shows the Popup
$find(ModalProgress).show();
}
function endReq(sender, args) {
// shows the Popup
$find(ModalProgress).hide();
}
var ModalProgress = '';
script>
<asp:Panel ID="pnlLoading" runat="server" CssClass="updateProgress">
<asp:UpdateProgress ID="updPrgPnl" runat="server">
<ProgressTemplate>
<div class="AlertModalBackground" runat="server" id="divBackground">
<asp:Panel ID="pnlLoadingImage" CssClass="updPrgPnl" runat="server">
<img src="~/Images/ajax-loader.gif" runat="server" id="loadingImage" alt="Cargando..." />
Cargando...asp:Panel>
div>
ProgressTemplate>
asp:UpdateProgress>
asp:Panel>
<asp:ModalPopupExtender ID="ModalProgress" runat="server" TargetControlID="pnlLoading"
BackgroundCssClass="modalBackground" PopupControlID="pnlLoading" />
<
asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">asp:ToolkitScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">

Y debajo de esto el resto de la página, los gif animados los podeis encontrar en la pagina ajaxload.info

Con esto ya deberíamos tener la ventanita cargando en la página.