在已經發布的 ASP.NET2.0 中,無重新整理頁面開發相關部分同 beta2 有不少改動。而且在越來越多的 Ajax 開發包被開發出來的情況下, ASP.NET2.0 內建的無重新整理頁面技術沒有被很多人瞭解,甚至不少人認為該功能有些“雞肋”。但如果我們僅僅是在程式中加入很少部分的 Ajax 特性 、Atlas 、Ajax.Net 等就顯得有些“殺雞用牛刀”的感覺了。而且,我認為使用 ASP.NET2.0 提供的方法進行開發並不很複雜,相反,使用很少的代碼就可以做出來很棒的效果!
下面我來一步一步的帶大家開發無重新整理的頁面!
第一步:實現 ICallbackEventHandler 介面
ICallbackEventHandler介面位於System.Web.UI命名空間下。在beta2時,ICallbackEventHandler只包含一個RaiseCallbackEvent方法,即處理回調事件,又返回處理結果。在正式版中,它變成了包含GetCallbackResult和RaiseCallbackEvent兩個成員方法,第一個用來返回回調事件的結果,第二個用來出來回調事件。這個變化主要是為了編寫Web控制項而做的改動,具體可以看一下GridView等控制項中的實現代碼。
建立一個 Web 網站,我們來修改 default.aspx.cs 檔案:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class _Default: System.Web.UI.Page, ICallbackEventHandler
{
protected void Page_Load(object sender, EventArgs e)
{
}
private string str;
public void RaiseCallbackEvent(string eventArgument)
{
//可以根據傳遞的參數不同,調用不同的處理邏輯
str = "從伺服器端返回的內容:" + eventArgument;
}
public string GetCallbackResult()
{
return str;
}
}
第二步:註冊回調方法
我們在 default.aspx 頁面中添加一個 TextBox ,一個 Label 和一個 Html 控制項 Button ,並給 Button 添加 onclick 事件:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!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 runat="server">
<title>無標題頁</title>
<script type="text/javascript">
<!--
//由button調用
function CallServer(inputcontrol,context)
{
context.innerHTML = "Loading";
arg = inputcontrol.value;
//註冊回調方法
<%= ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context")%>;
}
//在回調方法中註冊的接收返回結果的函數
function ReceiveServerData(result,context)
{
context.innerHTML = result;
}
// -->
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<input id="Button1" type="button" value="button" language="javascript" onclick="CallServer(TextBox1, Label1)" /><br />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></div>
</form>
</body>
</html>
好了,一個無重新整理的頁面就開發完了,它可以將你在 TextBox 中輸入的文字,通過伺服器代碼寫回到頁面的 Label 中。是不是很簡單?你可以運行一下你的程式看看效果啦!
下面我們來分析一下這些代碼。
首先,我們看<%= ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context")%>;
ClientScript是System.Web.UI.Page對象的一個屬性,它是System.Web.UI.ClientScriptManager對象。用於管理用戶端指令碼,GetCallbackEventReference方法用於註冊一個伺服器端事件的用戶端回調。它的第四個參數“Context”非常重要,但在MSDN中並沒有相關的例子和詳細的說明。在我上面給的代碼中可以看到,調用CallServer方法時,傳遞的Context參數就是Label1,而ReceiveServerData的第二個參數“Context”就是被傳遞過來的Label1。在我的例子中,Context被我用於設定一個用來顯示服務端返回結果的控制項。其實,你可以將任意的對象賦值給Context,它都會被傳遞給本地端處理回調返回結果的函數,這樣,你就可以根據調用前指定的“上下文”靈活的操作返回結果了!
在下面給出的完整例子中,你可以看到一個使用Context做的無重新整理顯示GridView的例子。
在這裡我要說個題外話,Context這麼重要的參數在MSDN中不但沒有詳細的說明,而且VS2005中文正式版MSDN中關於回調的例子竟然還是beta2時的實現!這個版本的MSDN可以說是我用過的版本中品質最差的。不過現在的MSND可以用“相當”龐大來形容,出錯也是在所難免的,希望下個版本的MSND會好一些。
OK,在ASP.NET 2.0中開發具有Ajax特性的東東不難吧!其實就是兩步:
1、在Server端實現ICallbackEventHandler介面,在介面包含的方法中根據傳遞的參數分別調用不同的處理方法,然後返回結果;
2、在Client端註冊回呼函數(當然你也可以在Server端註冊),然後實現處理回調結果的函數。其中,如果對Context能幹靈活運行,你就可以做出非常好的效果了。
.ASPX代碼
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!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 runat="server">
<title>ASP.NET 2.0 頁面提交無重新整理示範</title>
<script type="text/javascript">
function CallServer1(inputcontrol, context)
{
context.innerHTML = "<IMG SRC='images/pie.gif' />Loading";
arg = 'ServerMethod1|' + inputcontrol.value;
<%= ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData1", "context")%>;
}
function ReceiveServerData1(result, context)
{
context.innerHTML = context.id + ":" + result;
}
function CallServer2(obj)
{
context = gridspan;
context.innerHTML = "<IMG SRC='images/pie.gif' />資料載入中";
arg = "ServerMethod2|" + obj.value;
<%= ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData2", "context")%>;
}
function ReceiveServerData2(result, context)
{
context.innerHTML = result;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>Demo1:html按鈕提交資料</h1><br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<input id="Button1" type="button" value="提交到Label1" onclick="CallServer1(TextBox1, Label1)"/>
<input id="Button2" type="button" value="提交到Label2" onclick="CallServer1(TextBox1, Label2)"/>
<br />
<asp:Label ID="Label1" runat="server" Text="Label1:"></asp:Label>
<br />
<asp:Label ID="Label2" runat="server" Text="Label2:"></asp:Label>
</div>
<hr />
<div>
<h1>Demo2:伺服器按鈕提交資料</h1><br />
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:Button ID="Button3" runat="server" Text="Button" /><br />
<asp:Label ID="Label3" runat="server" Text="Label3:"></asp:Label></div>
<hr />
<div>
<h1>Demo3:下拉式清單方塊和gridview綁定資料</h1><br />
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ connectionStrings:test %>"
SelectCommand="select distinct(country) from customers"></asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ connectionStrings:test %>"
SelectCommand="select customerid, companyname, country from customers where country=@Country">
<SelectParameters>
<asp:ControlParameter Name="Country" ControlID="DropDownList1" PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<div>
<asp:DropDownList ID="DropDownList1" runat="server" Width="239px"
DataSourceID="SqlDataSource1" DataTextField="Country" DataValueField="Country">
</asp:DropDownList>
</div>
<br />
<span id="gridspan">
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource2">
</asp:GridView>
</span>
</div>
</form>
</body>
</html>
.CS代碼
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Globalization;
public partial class _Default : System.Web.UI.Page,ICallbackEventHandler
{
protected void Page_Load(object sender, EventArgs e)
{
//註冊用戶端事件處理方法
Button3.Attributes.Add("onclick", "CallServer1(TextBox2, Label3);return false;");
DropDownList1.Attributes.Add("onchange", "CallServer2(this)");
}
private string serverReturn;
public string GetCallbackResult()
{
//為便於查看載入效果,添加延時
System.Threading.Thread.Sleep(2000);
string[] parts = serverReturn.Split('|');
//根據傳遞的方法名進行調用,並傳遞相應的參數,目前只支援一個參數
return (string)GetType().GetMethod(parts[0]).Invoke(this, new object[] { parts[1] });
}
public void RaiseCallbackEvent(string eventArgument)
{
serverReturn = eventArgument;
}
//根據從用戶端傳來的英文國家名或縮寫,翻譯成相應的中文國家名
public string ServerMethod1(string arg)
{
string s;
switch (arg.ToLower())
{
case "cn":
case "china":
s = "中國";
break;
case "us":
s = "美國";
break;
default:
s = "未知國家";
break;
}
return s;
}
//根據從用戶端傳來的值,對GridView的內容進行更新,並將更新後的GridView的html返回
public string ServerMethod2(string arg)
{
DropDownList1.SelectedValue = arg;
GridView1.DataBind();
return RenderControl(GridView1);
}
private string RenderControl(Control control)
{
StringWriter writer1 = new StringWriter(CultureInfo.InvariantCulture);
HtmlTextWriter writer2 = new HtmlTextWriter(writer1);
control.RenderControl(writer2);
writer2.Flush();
writer2.Close();
return writer1.ToString();
}
}
Web.config
<configuration>
<appSettings/>
<connectionStrings>
<add name="test" connectionString="server=(local);Integrated security=true;database=pubs"/>
</connectionStrings>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
customers.sql
use pubs
go
create table customers
(
customerid int identity(1,1) primary key, --主鍵 自動成長
companyname varchar(20) not null, --公司名稱
country varchar(20) not null --所屬國家
)
insert into customers values ('中國公司','cn')
insert into customers values ('中國公司','china')
insert into customers values ('美國公司','us')
insert into customers values ('韓國公司','corea')
insert into customers values ('新加坡公司','singapore')
select * from customers