Olá pessoal! Nos posts anteriores, vimos como trabalhar com Banco de dados no C# utilizando uma classe que facilita e muito as operações com BD, principalmente as básicas (inserção, deleção, atualização e seleção). Agora, nesse post, vou dar uma dica de como dar um "tapa" no front-end de uma aplicação ASP.NET, ou seja, na interface com o usuário.

Você já deve ter visto por aí em alguns sites que quando executam uma operação, fica em algum lugar um indicador de processamento, algo como uma telinha escrito "Carregando" na página. Isto é feito utilizando-se AJAX, e serve basicamente para não "matar" o usuário de tédio enquanto o browser realiza alguma comunicação com o servidor assincronamente.

Se você já teve a oportunidade de trabalhar com o ASP.NET Ajax Extensions, deve ter visto um componente chamado UpdateProgress, não é? Ele serve justamente para fazer o que eu disse acima, ou seja, apresentar uma mensagem para o usuário enquanto um postback assíncrono é executado. Ele aparece quando a requisição é iniciada (quando clicamos em um botão, por exemplo) e some quando a página é atualizada.

Mas ele tem um incoveniente: Quando o postback é executado, o usuário tem total acesso aos outros elementos da página, dependendo de como você fez o conteúdo do UpdateProgress. Ou seja, enquanto uma requisição é processada, se o usuário clicar em qualquer outro botão, a requisição é cancelada e isso pode ter outros efeitos desagradáveis também. Vou mostrar uma maneira de como "travar" o acesso a página enquanto um postback é executado.

Para isso, vamos utilizar o excelente JQuery e o plugin jqModal.

Nossa ação vai consistir em fazer uma janela modal aparecer quando for solicitado um postback assíncrono da página; o overlay definido na janela modal irá bloquear o acesso aos elementos da página enquanto a requisição é processada. Também iremos incluir uma maneira do usuário cancelar o processamento, caso seja muuuuuuuuito longo (uma consulta demorada e com um filtro não bem delimitado por engano, por exemplo).

Para os exemplos, estarei utilizando o Visual Studio 2005.

Primeiro, crie um novo website habilitado para AJAX, e coloque o seguinte código no arquivo .aspx:

<%@Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!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 runat="server">
		<title>Exemplo de Ajax Loader Modal</title>
		<script type="text/javascript" src="jquery-1.2.6.pack.js" />
		<script type="text/javascript" src="jqModal.js" />
		<link rel="stylesheet" href="jqModal.css" />
		<style type="text/css">
			.AjaxLoader 
			{
				width:200px;
				height:200px;
				top:50%;
				left:50%;
				margin-left:-100px;
				margin-top:-100px;
				background-color:#0000FF;
				z-index:4000;
				text-align:center;
				position:absolute;
			}
		</style>
	</head>
	<body>
		<form id="form1" runat="server">
			<asp:ScriptManager ID="ScriptManager1" runat="server" />
			<asp:UpdatePanel runat="server" ID="UpdatePanel1">
				<ContentTemplate>
					<div>
						<asp:Button runat="server" ID="btnClickMe" Text="Clique-me :-)" OnClick="btnClickMe_Click" />
					</div>
				</ContentTemplate>
			</asp:UpdatePanel>
			<asp:UpdateProgress runat="server" ID="UpdateProgress1">
				<ProgressTemplate>
					<div id="dvAjaxLoader" class="AjaxLoader">
						<img src="ajax-loader.gif" alt="Carregando..." />
						<span style="color:White;font-family:Verdana;font-weight:bold;">Carregando...</span><br />
						<div style="width:100%;text-align:center;">
							<input type="button" id="btnCancelar" value="Cancelar Requisição" onclick="cancelPostback();" />
						</div>
					</div>
				</ProgressTemplate>
			</asp:UpdateProgress>
			<div id="dvModalLoader" style="width:0px;height:0px;left:-8000px;" class="jqmWindow">
			</div>
			<script type="text/javascript">
				//Inicializa o Modal
				var $dvModalLoader = $('#dvModalLoader').jqm({modal:true,toTop:true,trigger:false});
				
				//Adiciona os eventos para exibir/ocultar modal enquanto o postback assíncrono é executado.
				Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest); 
				Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
				
				function beginRequest(sender,args)
				{
					$dvModalLoader.jqmShow();
				}
				
				function endRequest(sender,args)
				{
					$dvModalLoader.jqmHide();
				}
				
				function cancelPostback()
				{
					Sys.WebForms.PageRequestManager.getInstance().abortPostBack();
					return false;
				}
			</script>
		</form>
	</body>
</html>

Coloque também o seguinte no code-behind:

protected void btnClickMe_Click(object sender, EventArgs e)
{
    Thread.Sleep(5000);
}

Com isso, construímos uma página que dentro de um UpdatePanel temos um botão, que ao ser clicado executará alguma coisa no servidor. Como não temos nada, coloquei apenas um delay, que é o suficiente para demonstrar o efeito do bloqueio da página.

Também colocamos um UpdateProgress, onde iremos construir a caixa que irá aparecer para o usuário ficar aguardando pelo carregamento da página. Nela tem uma figura, construída pelo site http://www.ajaxload.info/, um label e um botão, que ao ser clicado irá cancelar o postback. Um cuidado que devemos ter é colocar o atributo z-index do loader SEMPRE acima dos outros elementos da página, inclusive das janelas modais.

Além disso, temos um div que foi nomeado de "dvModalLoader", cuja classe CSS é "jqmWindow" (definida no arquivo jqModal.css) que define as características da janela modal para o plugin jqModal. Note que a largura e altura foram definidas para "0px" e posicionada com left em "-8000". A única coisa que iremos utilizar deste div é o overlay que o jqModal coloca para exibir a janela modal, e através dele bloquear o conteúdo atrás dele.

A mágica toda será executada através de JavaScript, então vamos a ele:

//Inicializa o Modal
var $dvModalLoader = $('#dvModalLoader').jqm({modal:true,toTop:true,trigger:false});

A linha acima inicializa o plugin jqModal, informando que o div dvModalLoader é uma janela modal. Através da variável $dvModalLoader é possível controlar a exibição da janela com os métodos jqmShow() e jqmHide() para exibir e ocultar, respectivamente.

Uma vez exibido a janela modal, os componentes que estão atrás dele não poderão ser clicados; somente poderemos usá-los após fechar a janela modal, o que pode ser feito com um botão dentro dela, chamando o método jqmHide().

O fluxo do botão "Clique-me :-)" fica assim: o botão é clicado, abre-se a janela modal, o UpdateProgress é exibido, é feito um processamento no servidor e após o processamento a página é atualizada e volta ao estado normal.

Para que essa janela modal apareça sempre ao efetuar uma chamada assíncrona ao servidor, juntamente com o UpdateProgress, iremos sobreescrever dois eventos da biblioteca AJAX, os eventos beginRequest e endRequest, que disparam quando uma chamada assíncrona é iniciada e finalizada, respectivamente.

//Adiciona os eventos para exibir/ocultar modal enquanto o postback assíncrono é executado.
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest); 
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);

function beginRequest(sender,args)
{
    $dvModalLoader.jqmShow();
}

function endRequest(sender,args)
{
     $dvModalLoader.jqmHide();
}

function cancelPostback()
{
    Sys.WebForms.PageRequestManager.getInstance().abortPostBack();
    return false;
}

No evento beginRequest, daremos o comando de exbição do dvModalLoader. Ao se iniciar um postback, o dvModalLoader é exibido e em seguida o UpdateProgress. Ao terminar a requisição ao servidor e a página for atualizada, é disparado o evento endRequest, ocultando o dvModal.

Construímos, no div que contém o Ajax Loader, um botão de cancelamento. No script acima, temos a função cancelPostback, que é a responsável por finalizar a requisição, disparando um endRequest e liberando a página para o usuário.

Como eu não tenho um local para hospedar o exemplo, vejam um vídeo com o efeito funcionando:

Os arquivos utilizados como exemplo do post estão na Página de Suporte do NeoMatrix Tech no link abaixo :-)

Exemplo de bloqueio de tela nas requisições ASP.NET AJAX usando jQuery (29 KiB)

Um abraço a todos!