65.9K
CodeProject 正在变化。 阅读更多。
Home

锁定 ASP.NET 页面并在等待长 POST 回显时显示动画图像

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (31投票s)

2009年4月7日

CPOL

4分钟阅读

viewsIcon

273104

downloadIcon

11151

锁定页面,防止回发

引言

问题

Web 中最普遍的问题之一是提交后需要很长时间才能处理的页面。假设您有一个 ASP.NET 表单,处理时间长达 30 秒,用户会不断地按提交按钮两到三次,希望能更快地获得信息(这可能会导致数据问题)。解决此问题的一种方法是在提交按钮被按下后禁用它。但如果您的表单中有多个按钮怎么办?

解决方案

在本文中,我将向您展示如何在 POST 回显期间禁用所有 ASP.NET 表单的控件,并在页面 POST 回显时向用户显示一个友好的动画 GIF。事实上,如果您对漫长的等待感到厌烦,甚至可以移动这个小框。

Yahoo to Yahoo

Yahoo 为我们提供了一个完整的、可供下载并在我们的 Web 应用程序中免费使用的 JavaScript 框架!那么为什么不利用它呢?您可以在此处找到有关它的更多信息。

在本文中,我将仅使用 Yahoo YUI 的Panel对象。以下是入门的几个简单步骤:

此处下载框架脚本到您的项目(v. 2.7)。

框架应该在一个名为YUI的目录中(我下载了 2.7.0 版本)。将此目录复制到您的 Web 项目中,您的 Web 项目应如下所示:

WebProjectWithYUIFolder.gif

Show Me the Money Jerry!

现在我们已经在项目中设置了 Yahoo Framework,我们可以开始工作了!以下是设置您的 ASP.NET 页面以充分利用Panel对象的几个简单步骤(此处)。

在 HTML 的<head>标签下,包含这些 JavaScript 文件:

<!-- YUI CSS -->
<link rel="stylesheet" type="text/css" href="yui/build/container/assets/container.css"/>
<link rel="stylesheet" type="text/css" href="yui/build/menu/assets/skins/sam/menu.css"/>
<!-- YUI Dependencies -->

<script type="text/javascript" src="yui/build/utilities/utilities.js" ></script> 
<script type="text/javascript" src="yui/build/container/container-min.js"></script>
<script type="text/javascript">

让我们创建几个简单的 JavaScript 函数:让我们开始初始化Panel,标题为“正在加载,请稍候…”并使用一个名为Wait.gif的动画 GIF(您可以为该对象添加更多属性,请阅读 Yahoo 文档)。

// sets up all of the YUI dialog boxes
function InitDialogs() {
DialogBox_Loading = new YAHOO.widget.Panel("waitBox", 
	{ fixedcenter: true, modal: true, visible: true, 
	width: "230px", close: false, draggable: true });
DialogBox_Loading.setHeader("Loading, please wait...");
DialogBox_Loading.setBody('<div style="text-align:center;">
	<img src="images/Wait.gif" id="Image1" /></div>');
DialogBox_Loading.render(document.body);
}

让我们创建一个 JavaScript 函数,该函数负责根据布尔值显示或隐藏“等待框”。我们还想确保 ASP.NET 页面是有效的(所有 ASP.NET 验证控件都已成功)之后,我们才显示Panel对象。我们可以使用客户端的Page_IsValid标志来检查这一点。为了获取此标志,我们被迫在按下按钮时调用 .NET 生成的 JavaScript 方法Page_ClientValidate();。我将在文章稍后展示这一点。

function Loading(b) {
    if (b == true && Page_IsValid == true) {

    DialogBox_Loading.show();
}

else {

    DialogBox_Loading.hide();
}
}

对于此示例,我添加了 AJAX 脚本管理器,以便可以在客户端使用pageLoaded()事件。要了解更多信息,请在此处访问。如果您不想使用 Ajax Framework,那么我们需要自己连接 JavaScript 中的页面加载事件。这是一个如何做的示例:让我们添加一个帮助 JavaScript 函数,它将为页面加载事件调用我们想要的任何函数。我已经将该示例包含在我的下载示例项目中的YahooWaitLoadOnButtonServerNoAjax.aspx下。这是一个使用 JavaScript 实现此功能的有效示例:

function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}

// wire up the PageLoad function with our helper function addLoadEvent
addLoadEvent(function() {
pageLoad();
})

在 Page Load 事件中,我将初始化 Dialog 框而不显示它。

function pageLoad() {
InitDialogs();
Loading(false);
}

现在我们准备创建一些 ASP.NET 控件,让我们创建一个文本框、一个 Required Field Validator 和一个需要 30 多秒才能处理的 ASP.NET 按钮。我们将把几个 JavaScript 调用链接到我们的按钮。

<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="false" />
<div>

<asp:TextBox ID="txtFirstName" runat ="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="VtxtFirstName" ControlToValidate="txtFirstName" 
	ErrorMessage="error" runat="server"></asp:RequiredFieldValidator>
<asp:Button ID="btnPushLongJob" Text ="Start Long Job" runat="server" 
    OnClientClick="Page_ClientValidate();Loading(true);" OnClick="btnPushLongJob_Click"/>
</div>
</form>
</body>

我正在调用Page_ClientValidate(),这是一个由我的 ASP.NET Validator 控件生成的 JavaScript 函数。我被迫调用它,以便它可以设置客户端的Page_isValid标志,该标志在Loading JavaScript 函数中使用。并且我调用Loading(true)来显示 Dialog 框。

现在,让我们在代码隐藏中为按钮的Onclick事件添加一个长时间处理的任务(记住添加System.Threading命名空间以使用Thread类)。

protected void btnPushLongJob_Click(object sender, EventArgs e)
{
        Thread.Sleep(30000);
}

问题:GIF 动画在 POST 回显期间停止

嗯,生活有时很艰难,并非一切都如预期般工作。由于某些原因,Internet Explorer 决定让我们的生活更艰难,并在 POST 回显期间停止所有 GIF 动画,但有一个解决方法,我现在就免费向您展示(我很善良,对吧?)。在 JavaScript 中重置图像源似乎可以解决此问题。

我添加了以下 JavaScript 代码:

function UpdateImg(ctrl, imgsrc) {
var img = document.getElementById(ctrl);
img.src = imgsrc;
}

并且我在 Page Load 事件中从代码隐藏将其链接到我的 ASP.NET 按钮。

protected void Page_Load(object sender, EventArgs e)
{
btnPushLongJob.Attributes.Add("onclick", 
	"setTimeout(\"UpdateImg('Image1','images/Wait.gif');\",50);");
}

这样我们就完成了!

这是一个完整的页面代码:

<%@ Page Language="C#" AutoEventWireup="true" 
	CodeFile="YahooWaitLoadOnButtonServerSide.aspx.cs" 
	Inherits="YahooWaitLoadOnButtonServerSide" %>
<!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 id="Head1" runat="server">
<title></title>

<!-- YUI CSS -->
<link rel="stylesheet" type="text/css" href="yui/build/container/assets/container.css"/>
<link rel="stylesheet" type="text/css" href="yui/build/menu/assets/skins/sam/menu.css"/>
<!-- YUI Dependencies -->

<script type="text/javascript" src="yui/build/utilities/utilities.js" ></script> 
<script type="text/javascript" src="yui/build/container/container-min.js"></script>
<script type="text/javascript">

function pageLoad() {
InitDialogs();
Loading(false);
}

function UpdateImg(ctrl, imgsrc) {
var img = document.getElementById(ctrl);
img.src = imgsrc;
}

// sets up all of the YUI dialog boxes
function InitDialogs() {
DialogBox_Loading = new YAHOO.widget.Panel("waitBox", 
	{ fixedcenter: true, modal: true, visible: true, 
	width: "230px", close: false, draggable: true });
DialogBox_Loading.setHeader("Loading, please wait...");
DialogBox_Loading.setBody('<div style="text-align:center;">
	<img src="images/Wait.gif" id="Image1" /></div>');
DialogBox_Loading.render(document.body);
}
function Loading(b) {
if (b == true && Page_IsValid == true) {
DialogBox_Loading.show();
}
else {
DialogBox_Loading.hide();
}
}
</script>
</head>
<body>

<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="false" />
<div>

<asp:TextBox ID="txtFirstName" runat ="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="VtxtFirstName" 
	ControlToValidate="txtFirstName" ErrorMessage="error" 
	runat="server"></asp:RequiredFieldValidator>
<asp:Button ID="btnPushLongJob" Text ="Start Long Job" runat="server" 
    OnClientClick="Page_ClientValidate();Loading(true);" OnClick="btnPushLongJob_Click"/>
</div>
</form>
</body>
</html>

这是代码隐藏文件的完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
public partial class YahooWaitLoadOnButtonServerSide : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
btnPushLongJob.Attributes.Add("onclick", 
	"setTimeout(\"UpdateImg('Image1','images/Wait.gif');\",50);");
}
protected void btnPushLongJob_Click(object sender, EventArgs e)
{
Thread.Sleep(3000);
}
}

代码

我创建了一个包含 Yahoo YUI 2.7 Framework 的示例项目。您可能想尝试YahooWaitLoadOnButtonServerSide.aspx页面作为此示例(对于没有 Ajax 支持的情况,请查看YahooWaitLoadOnButtonServerNoAjax.aspx页面)。我还包含了一些其他示例,例如工具提示和使用 Page Methods 的 Dialog 框。

您可以通过本文顶部的链接下载代码。

希望您喜欢这篇文章,并且它让您的生活变得更轻松。

© . All rights reserved.