(轉自:Windy的專欄)
原文地址:http://sharethispoint.com/archive/2006/11/15/Build-web-parts-with-ajax.aspx
如何在開發Web組件時使用ajax呢?我們將以一個樣子類似MOSS 2007中KPI和BDC Web組件的WebPart為例來說明。如果你對ajax一點都不瞭解,推薦學習TerryLee的ajax入門系列。
ASP.net2.0有一個很酷的新特性叫作用戶端指令碼回調。指令碼回調主要使我們可以使用javascript調用伺服器端程式中的方法,然後根據結果來做一些操作。這就使我們可以動態更新頁面的某一部分內容,正如將在我們下面的WebPart中看到的,而不必重新整理整頁。關於在.net2.0中使用用戶端指令碼回調,可以參考下面的文章地址(http://msdn.microsoft.com/msdnmag/issues/04/08/CuttingEdge/),其中做出了詳細的解釋。但是如何確切的將其使用與我們的代碼中,文章並沒有詳細介紹。事實上指令碼回調特性是整合到.net中的,我們可以方便的拿來使用。
本樣本中我們假設有這麼一個WebPart,它需要很長的時間才能顯示出內容。為瞭解決這個問題,給使用者更好的體驗,我們決定讓render方法在WebPart剛剛載入時只輸出一個空的div標籤,然後我們通過ajax來替換div的內容,使其顯示出實際需要的內容。這樣,使用者就可以在頁面載入後在我們的WebPart完成內容載入前先看一看其他的內容。
下面我們就開始。
首先我們先建立一個新的WebPart項目。在我們的WebPart類中添加下面的命名空間。
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
想要使.net知道我們的類要使用指令碼回調,必須實現System.Web.UI.IcallbackEventHandler介面。
public class TreeViewRollUp:WebPart,ICallbackEventHandler
IcallBackEventHandler介面有兩個方法,public string GetCallbackResult()和 public void RaiseCallbackEvent(string eventArgs),稍後將對其進行介紹。
我們先定義兩個變數
private string datadiv; //用於儲存div標籤名稱
private string ajaxdata; //用於儲存ajax返回的資料
datadiv變數儲存了html中的我們打算輸出內容的div標籤的id。這個div標籤的名稱在一個WebPart執行個體中必須唯一。如果始終是一個固定名稱,那麼當我們在一個頁面中有兩個webpart的執行個體時它們有可能會替換對方的內容。
在webpart的RenderContents方法中加入下面的代碼:
protected override void RenderContents(HtmlTextWriter writer)
{
this.datadiv = this.ClientID + "content"; //使用WebPart執行個體的用戶端id 加上一個給定的名稱
writer.Write("<div id=\"" + this.datadiv + "\"><img src=\"/_layouts/images/GEARS_AN.GIF\" width\"150\"></div>");
}
我們在最後一行的div標籤中加了一個進度條的小gif圖。這裡直接用了WSSv3中的圖片。
在OnLoad中粘貼如下代碼:
protected override void OnLoad(EventArgs e)
{
this.datadiv = this.ClientID + "content";
string js = Page.ClientScript.GetCallbackEventReference(this, "'blah'", "filldiv", "'" + this.datadiv + "'", true);
string contentloader= "var ajaxcommands='';window.onload = ajaxloader; function ajaxloader() { eval(ajaxcommands); } function filldiv(arg, ctx){ var mydiv = document.getElementById(ctx); mydiv.innerHTML = arg;}";
if (Page.ClientScript.IsClientScriptBlockRegistered("contentloader") == false)
Page.ClientScript.RegisterClientScriptBlock(Page.ClientScript.GetType(), "contentloader", contentloader, true);
Page.ClientScript.RegisterStartupScript(this.GetType(), "myloader"+this.ClientID, " ajaxcommands = ajaxcommands + \"" + js + ";\";", true); //使用WebPart執行個體的用戶端id 加上一個給定的名稱作為指令碼的Key
base.OnLoad(e);
}
在該方法中註冊有兩塊不同的javascript塊 。
第一個字串js的值來源於GetCallbackEventReference。GetCallbackEventReference方法用於返回執行回調伺服器擷取資料的javascript。我們傳遞了:一個當前控制項(webpart)的引用;“Blah”,作為初始資料當回調啟動後將被傳遞到我們的伺服器端組件;當回調結束後調用的Javascript方法的名字;我們的標記內容的div標籤的名字;非同步開關設為true這些必要的參數。
通過該方法產生的javascript類似於下面的樣子:
WebForm_DoCallback('ctl00$m$g_a010b3bd_1a68_40f9_b46b_f87050cf516f','blah',filldiv,'ctl00_m_g_a010b3bd_1a68_40f9_b46b_f87050cf516fcontents',null,true);
我們可以將這段javascript用於一個button的OnClick事件來啟動回調並填充div標籤。
在本例中,我們不希望使用者還要點擊什麼的才能繼續WebPart的載入。所以我們要在瀏覽器載入頁面時調用WebForm_DoCallback 方法。這是用contentloader字串來實現的。Contentloader字串定義了一個javascript變數, ajaxcommands, 用來儲存我們準備執行的一些命令。同時,我們設定window.onload事件使其執行ajaxloader方法。當ajaxloader方法運行時將通過eval函數執行所有存在ajaxcommands變數中的命令。
為什麼這麼寫呢?這是因為如果我們在一個頁面裡有多於兩個的ajax webpart的執行個體時,每個執行個體都將會通過window.onload事件來載入資料,這樣問題就產生了。只有最後設定的事件處理(Event Handler)會被執行,並不是所有的設定都執行。為此,我們打了一個擦邊球。在window.onload裡設定了一個command方法。每一個webpart僅僅擴充其WebForm_DoCallback到ajaxcommands 變數。這樣,起碼解決了本例中的問題。應該算得上一個好辦法吧。
最後,contentloader字串也包括了filldiv方法,用於設定div中的回調所返回的html內容。
最後一步,在我們的類的OnLoad 方法中將指令碼註冊到頁面中。我們只需要在一個頁面裡有一個contentloader javascript指令碼。所以,我們在註冊前先判斷是否已經被頁面中其他的WebPart通過指令碼管理器註冊了。
剩下的事兒就是實現IcallbackEventHandler介面所需要的兩個方法。
string ICallbackEventHandler.GetCallbackResult()
{
return this.ajaxdata;
}
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
this.ajaxdata="Some crazy message here!<BR>"+this.ClientID;
}
RaiseCallbackEvent當用戶端回調啟動時將被調用。它是一個無傳回值的方法,僅用於將GetCallbackResult方法需要的資料準備好。
RaiseCallbackEvent方法是我們放置所有用於返回給webpart的render方法要顯示內容的相關代碼的地方。本例中我們只發送一條簡單的資訊給用戶端。為了區分不同的WebPart執行個體確實做了各自的工作,我們在資訊後加上了各自的ClientID
趕快動手實踐一下吧,希望大家對使用用戶端回調已經入門了。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1524249