ASP.NET 2.0中callback的一些變化+使用示例(上)

轉自:http://tb.blog.csdn.net/TrackBack.aspx?PostId=1761990

可能你覺得callback很弱,AJAX才夠強。其實網上大多數callback的示例代碼都是不太正確的(包括MSDN)。這裏提供了一種不同的使用callback的方法。只用很少的javascript就實現了一個聯級下拉清單。你會發現:羽量級的callback其實也很好用。

在這裏我有兩個DropDownList,ddlCategory和ddlProduct。要求ddlCategory變化後ddlProduct無刷新的填充新的專案。

要使用Callback首先要繼承ICallbackEventHandler介面:

public partial class Callback : Page, ICallbackEventHandler 或:

<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

正式版的ICallbackEventHandler要實現以下兩個方法:

string GetCallbackResult ()
void RaiseCallbackEvent (string eventArgument)

eventArgument現在改為由RaiseCallbackEvent接收,而不是由GetCallbackResult直接接受了。目的是為了讓你可以在RaiseCallbackEvent中做一些初始化操作,這點在編寫支援callback的控制項時特別有用,有興趣的話你可以參考GridView和DetailView中RaiseCallbackEvent的代碼。在這裏我只使用最簡單的方式,把eventArgument存到一個私有成員中: private string _callbackEventArgument;

protected virtual void RaiseCallbackEvent(string eventArgument)
{
     this._callbackEventArgument = eventArgument;
}

在用戶端觸發callback需要使用到GetCallbackEventReference,正式版中的GetCallbackEventReference位於Page.ClientScript下。ClientScript是2.0中Page的一個新增成員,專門用於處理用戶端教本(javascript),它是一個實例化的ClientScriptManager。

<script type="text/javascript">
   function CallServer(arg, context)
     {
      <%= ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context")%>;
      }

    function ReceiveServerData(result, context)
      {
          ...
      }
</script>

protected void Page_Load(object sender, EventArgs e)
{
    ddlCategory.Attributes.Add("onchange", "CallServer(....)");
}

f在這裏我使用了一個javascript函數CallServer來包裝callback的觸發,當然你也可把它直接掛到onchange或其他用戶端事件上。不過用一個函數來包裝的話,可以很方便的在callback前後做一些其他操作,下面我就會用到。

不知道你有沒有發覺,我們傳給callback兩個參數:arg和context,但是RaiseCallbackEvent只得到一個(arg),另一個參數context會給原封不動的傳給ReceiveServerDate。這個context到底有什麼用呢?甚至連MSDN裏的代碼也沒有很正確的使用這個參數。可能你覺得callback很弱,只傳入一個string(arg)傳出一個string(result),還要編寫大量的javascript代碼才能實現想要的功能。其實,只要正確使用上面那個context參數就可以用很少的javascript實現很理想的功能。

首先,我們拆分一下arg,把我們要調用的服務端方法放進去:

ddlCategory.Attributes.Add("onchange", "CallServer('FillProduct|'+this.value, ...)");

然後用反射在伺服器端調用這個方法(FillProduct):

public string GetCallbackResult()
{
    string[] parts = _callbackEventArgument.Split('|');
    return this.GetType().GetMethod(parts[0]).Invoke(this, new objcet[]{parts[1]}) ;
}

我們來看看FillProduct會返回些什麼:

public string FillProduct(string categoryID)

    ddlCategory.SelectedValue = categoryID; 
    ddlProduct.DataBind(); 
    StringWriter writer1 = new StringWriter(CultureInfo.InvariantCulture); 
    HtmlTextWriter writer2 = new HtmlTextWriter(writer1); 
    ddlProduct.RenderControl(writer2); 
    writer2.Flush(); 
    writer2.Close();
    return writer1.ToString();
}

你可以看到,我把需要更新的ddlProduct整個重新Render後傳回來了,也就是說要用新生成的ddlProduct的HTML替換原來的ddlProduct的HTML。怎麼做到這一點呢?context參數要出馬了:

<script type="text/javascript">
   function CallServer(arg, context)
     {
        context.innerHTML = "Loading";
        <%= ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context")%>;
      }

    function ReceiveServerData(result, context)
      {
        context.innerHTML = result;
      }
</script>

.....

<asp:DropDownList ID="ddlCategory" runat="server"    DataSourceID="SqlDataSource1" 
      DataTextField="CategoryName" DataValueField="CategoryID" AppendDataBoundItems="True" > 
    <asp:ListItem Value="">- Select Category -</asp:ListItem>
</asp:DropDownList>
<span id="_span1"> 
    <asp:DropDownList ID="ddlProduct" runat="server"    DataSourceID="SqlDataSource2" 
            DataTextField="ProductName" AppendDataBoundItems="True"> 
          <asp:ListItem Value="">- Select Product -</asp:ListItem> 
    </asp:DropDownList>
</span>

protected void Page_Load(object sender, EventArgs e)
{
    ddlCategory.Attributes.Add("onchange", "CallServer('FillProduct|'+this.value, _span1)");
}

原來我把要更新的ddlProduct放在_span1裏,context就是用來傳遞這個_span1的。只要用新生成的HTML填充這個_span1,ddlProduct的更新就OK了。這樣我們就很輕鬆的完成了一個無刷新的聯級下拉清單。

需要注意的是,要在頁面提交(postback)後取得這個ddlProduct的值,需要使用 Request.Form[ddlProduct.UniqueID] 因為viewstate並沒有被更新。

更新:或者可以把ddlProduct的EnableViewState改為False,然後就可以用ddlProduct.SelectedValue取值了。但是這樣做在複雜的頁面中可能會引起一些錯誤,要更具具體情況謹慎處理。

 

ASP.NET 2.0中callback的一些變化+使用示例(上)

ASP.NET 2.0中callback的一些變化+使用示例(中)

ASP.NET 2.0中callback的一些變化+使用示例(下)


arrow
arrow
    全站熱搜

    Roger 發表在 痞客邦 留言(0) 人氣()