在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在这里我有两个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(....)"); } 在这里我使用了一个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">
protected void Page_Load(object sender, EventArgs e)
{ ddlCategory.Attributes.Add("onchange", "CallServer('FillProduct|'+this.value, _span1)"); }
其实你可以把这两部分整理到一个CallbackHelp类中,这样复用性就更高了。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Callback.aspx.cs" Inherits="Callback" %>
<!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"> <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> <head runat="server"> <title>Callback</title> </head> <body> <form id="form1" runat="server"> <div> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString1 %>" SelectCommand="SELECT [CategoryID], [CategoryName] FROM [Categories]"> </asp:SqlDataSource> <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString1 %>" SelectCommand="SELECT [ProductID], [ProductName] FROM [Products] WHERE ([CategoryID] = @CategoryID)"> <SelectParameters> <asp:ControlParameter ControlID="ddlCategory" Name="CategoryID" PropertyName="SelectedValue" /> </SelectParameters> </asp:SqlDataSource> <div id="_div1" runat="server"> <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><span id="_span2"> <asp:Button ID="btnBuy" runat="server" Text="Buy" Enabled="false" OnClick="btnBuy_Click" /> <br /> </span> </div> <asp:Label ID="Label1" runat="server"></asp:Label> </div> </form> </body> </html>
using System;
using System.IO; using System.Collections; using System.Globalization; using System.Reflection; using System.Web; using System.Web.UI; public partial class Callback : Page, ICallbackEventHandler |
请发表评论