AJAX DropDownList

分享于 

17分钟阅读

Web开发

  繁體

Sample Image - ajaxdropdownlist.gif

介绍

AJAX ( 异步JavaScript和 XML ) 已经变得如此流行,因为谷歌建议。 AJAX已经开启了更具响应性和交互性的web应用程序,使它的更接近 Windows。 网络开发者是那些在第一时间快乐的人。 他们有一个新玩具,它们由旧玩具组成,现在他们可以用玩具来制造酷的东西。 另一方面,在GMail中获得免费帐户后,最终用户需要更多的部门web应用程序。 他们讨厌 postback,他们不想刷新,而且一切只是停留在那里,但仍然得到。 是否可能?

那些要求用户的用户是我创建这个定制控件的动机。 让我来介绍 AjaxDropDownList,我第一次尝试贡献AJAX世界。 AjaxDropDownList 是一个具有以下功能的dropdownlist控件:

  • 从服务器源异步提取 background 中的数据,而不使用 postback。
  • 可以触发其他dropdownlists的更改事件,从而产生级联链接的dropdownlist效果。
  • 被封装到一个可以轻松拖放到设计器中或者从服务器代码中添加的单个控件中。
  • 使用通用代码访问 selectedItem 就像普通的dropdownlist一样,因此可以轻松地与其他UI框架集成。
  • IE 6,Mozilla Firefox 1.04和 Netscape 8.02兼容。

虽然我将该控件称为 AjaxDropDownList,但它不使用XML传输数据。 我使用的是 Douglas,它是道格拉斯的( JavaScript对象表示法),它更轻量级,可以被JavaScript作为一个对象使用。 我意识到XML与JSON相比具有潜在的灵活性和灵活性。 但是在我的例子中,JSON足以满足需求。

如何使用控件

从示例项目开始

在 VS.NET 2003中下载并打开项目。 编辑 GetLookupData.aspx.cs 并更改连接字符串以指向有效的NorthWind数据库。 如果由于某些原因,你没有NorthWind数据库,你可以从Microsoft下载数据库脚本。 在Google上搜索一下。

成功构建解决方案后,运行并浏览 Default.aspx。 评估这里控件是否为你要查找的控件。

演示的内容

在这个演示页面中,我们有三个 AjaxDropDownList s: 客户( ddlCustomers ),订单( ddlOrders ) 和产品( ddlProducts )。

订单dropdownlist依赖于客户。 这意味着如果我们在on中进行选择,那么将根据我们的选择筛选订单 listviewitem。 此外,产品取决于订单。 所以选择客户会触发订单的变更,随后触发产品的变更。 请注意,所有这些都发生在没有。

在使用dropdownlist时,你可能会遇到一个显示错误消息的JavaScript警告框。 它可以能意味着很多事情,但是很可以能你的数据库连接不起作用。

现在按下提交按钮,页面将 finally 执行 postback。 每个dropdownlist的选定文本将显示在右侧。 这说明在 ASP.NET DropDownList 中访问选择的标准代码仍然适用于 AjaxDropDownList

里面有什么

有三个重要部分:

  • AjaxDropDownList.cs

    它包含自定义控件。 将这里文件放入一个单独的类库项目中,这样我们就可以将控件添加到工具箱中而无需任何麻烦。

  • Default.aspx

    它是一个使用 AjaxDropDownList 控件的示例网页。 控件从工具箱中拖放到设计器中。

    如果要将 AjaxDropDownList 添加到工具箱中,请右键单击工具箱窗格,然后选择添加/删除项。 它将打开自定义工具箱对话框。 按浏览按钮,然后选择 CustomControl.dll 或者包含 AjaxDropDownList的程序集。 将出现一个带有复选框的大控件列表。 确保选中 AjaxDropDownList 并关闭对话框。 控件将出现在工具箱中,可以将它的拖放到设计器。

  • GetLookupData.aspx

    这是处理 xmlHttp 请求的页面,并返回适当的JSON。 它需要处理两个查询字符串:

    • " id"是查找 NAME 或者标识符。比如。国家。货币。订单。产品和 InvoiceStatus。
    • " filter"( 可选) describes名称值对。比如。客户。ALFKI中的筛选器。

    请求如下:

    http://localhost/GetLookupData.aspx?id=Orders&filter=Customer,ALFKI

    翻译为:

    "Get data from Orders for Customer code = ALFKI"

    这取决于你如何实现请求处理程序。

    警告:GetLookupData.aspx 只是一个简单的例子,不适合于产品环境。

代码演练

AjaxDropDownList 控件严格使用 JavaScript。 代码被嵌入到控件中,当控件呈现时将被注入到响应流中。 为了最小化HTTP负载,JavaScript代码已经使用 JavaScript Minifier 最小化。 然而,这将对实际代码的调试困难和令人沮丧。

因此,在示例项目中,我以原始格式提供源代码,并且所有注释仍在。 在本演练中,请参考 SourceScript.aspx。

XMLHTTP

JavaScript代码利用 xmlHttp 对象以异步或者同步的方式对web服务器发出请求。 由于可以在不刷新页面的情况下进行请求,因这里网页看起来更响应和交互。 在对 xmlHttp 对象的get引用,调用 getXMLHTTP() 方法,而不管浏览器如何实现这里对象。

控制器

每个 AjaxDropDownList 都呈现为 <选择> 元素。这些元素中的每个元素都有它的控制器,称为 AjaxDropDownController。 控制器有很多要做的事情:

  • 对web服务器执行异步请求以获取数据。
  • 填充 dropdownlist。
  • 侦听dropdownlist的更改事件。
  • 成为观察者和观察者。
  • 在客户端保存dropdownlist的内容。

在Model-View-Controller的上下文中考虑控制器,即 <选择> 图中,虽然我不想强调这个 Pattern,但作为模型,位于web服务器中的数据,以及控制器本身作为控制器,尽管我不想强调这一点。

执行异步 background 请求

当控制器需要更新它的dropdownlist时,它将调用 load(),然后调用 getSource()。 调用这些方法时,它可能传递筛选器字符串,它是它所依赖的dropdownlist的名称值对。 inside的getSource() 方法,构建了一个请求 URL,它包含 idfilter 参数。

var requestUrl = baseUrl + "?id=" + self.lookupName;if (filter!= undefined && filter!= "") 
{ 
 requestUrl += "&filter=" + filter; 
}

然后,对 xmlHttp 对象的引用进行保护后,将发送请求。 注意 xmlHttp.open 中的最后一个参数设置为 true 指示异步请求。

xmlHttp = getXMLHTTP(); if (xmlHttp) 
{ 
 xmlHttp.onreadystatechange = doReadyStateChange; 
 xmlHttp.open("GET", requestUrl, true); 
 xmlHttp.send();
}

由于请求的本质是异步的,所以我们无法确定响应什么时候可用。 因此,我们将事件处理程序 doReadyStateChange 分配给 onreadystatechange 属性。 这里事件处理程序将在请求的状态发生更改时被调用。

function doReadyStateChange(){
 if (xmlHttp.readyState == 4)
 {
 if (xmlHttp.status == 200)
 {
 eval("var d=" + xmlHttp.responseText);
 if (d!= null)
 {
 populateList(d);
 }
 }
 else {
 alert("There was a problem retrieving the XML data:n" +
 xmlHttp.statusText);
 }
 }
 }
}

doReadyStateChange 中,我们检查 readyState = 4,它表示"完成"和 status= 200,指示一个"行"http。 一旦满足这些条件,就应该处理响应流了。

处理响应流

如前所述,我使用JavaScript对象表示法( JSON ) 将数据从web服务器传输到客户端。 JSON比XML更轻量级,可以轻松转换为JavaScript对象层次结构。

例如当我们发送这样的请求时:

http://localhost/GetLookupData.aspx?id=Product&filter=Order,10280

服务器将返回:

[{"value":"24","name":"Guaraná Fantástica"},
{"value":"55","name":"Pâté chinois"},
{"value":"75","name":"Rhönbräu Klosterbier"}]

我们用另一个字符串连接 responseText,以生成有效的JavaScript语句并使用 eval 执行语句。

eval("var d=" + xmlHttp.responseText);

因此,在内存对象层次结构中创建如下所示:

d +--- [0] +--- value: 24
 | |--- name: Guaraná Fantástica
 |
 +--- [1] +--- value: 55
 | |--- name: Pâté chinois
 |
 +--- [2] +--- value: 75
 |--- name: Rhönbräu Klosterbier

我们可以轻松地遍历对象层次结构,例如:

  • d[0].value 将返回 24.
  • d.length 将返回 3。

然后将这里对象传递给 populateList(),后者负责填充相应 <选择> 元素。populateList 将首先清除从 选择 然后,迭代对象层次结构并创建新的选项项。

观察者 Pattern

AjaxDropDownController 实现观察者 Pattern。 一个 AjaxDropDownController的实例既可以是观察者,也可以是观察者。 每个实例保存一个观察者列表,这样当相应的dropdownlist中发生值更改时,控制器可以通知每个观察者关于更改的。

观察者列表保存在这里数组中:

var observers = [];
方法
  • addObserver()

    调用这里方法将新的观察者添加到列表中。 将该列表添加到列表之前,它将检查新的观察者是否已经在列表中,从而确保。

  • removeObserver() - 省略。

    观察者 Pattern的完整实现需要这种方法。 调用这里方法以从列表中移除观察者。 目前,我没有看到任何实用的用法,所以我没有实现这个方法。

  • notify()

    我们调用这里方法通知所有观察者有关相应的dropdownlist中的更改。 这里方法将基于formview的selectedIndex 构造一个筛选字符串,然后遍历观察器列表并调用 load() 方法。

  • load()

    调用这里方法时,控制器将调用 getSource 以使用 xmlHttp 异步获取源数据。

持续内容

在客户端的内容更改时,在 postback 期间不会将更改转移到服务器端。 因这里,我们不能使用标准代码访问listviewitem中选定的项目,比如 使用ipqos的selectedItem 或者 selectedIndex。 当我们想将控件合并到数据绑定框架中,或者仅仅是无法编写特殊代码来处理控件时,就会出现问题。

这就是为什么我将dropdownlist的内容保存在客户端的原因。 对于每个 AjaxDropDownList,将有一个与之关联的隐藏字段。 隐藏字段是将dropdownlist内容作为值分隔字符串 e.g.的容器:

24|Guaraná Fantástica|55|Pâté chinois|75|Rhönbräu Klosterbier

控件中的分隔符是可以配置的。 因此,如果你不喜欢'|',你可以更改为另一个字符。

在 postback 中,将读取分隔字符串,并在dropdownlist中创建相应的项。

服务器端

关于代码的讨论没有完成,而且不触摸服务器端,因为这是数据来源的地方。 客户端不同,服务器端代码相对简单。 基本上我们需要处理 xmlHttp 发送的请求,并以JSON的形式提供数据。

这取决于你如何从数据库中获取数据。 GetLookupData.aspx 不是一个很好的例子,因为它容易受到 SQL注入 攻击。 在实际的情况下,你可能需要调用数据访问框架而不是直接连接到数据库。 你还可能需要缓存内存中的数据以保存到数据库的往返。

客户端最重要的是返回到客户端的响应的格式。 必须采用以下格式:

[ {"value":"value1","name","name1"},
{"value":"value2","name","name2"},
.. .
{"value":"valueN","name","nameN"} ]

value1.valueN表示项目值和 name1.。 nameN表示项目文本。

自定义控件

AjaxDropDownList 是自定义控件,自 System.Web.UI.WebControls.DropDownList 它封装了从客户端提供动态数据填充的所有代码,并让dropdownlist参与链接的dropdownlist链。

它在 DropDownList的标准属性顶部有四个附加的public 属性:

  • Observers

    是观察者对象的ArrayList。 当你向其中添加另一个 AjaxDropDownList 时,AjaxDropDownList 将变得依赖于当前的DropDownList。 例如:

    DropDownList1.Observers.Add(DropDownList2);

    它将使 DropDownList2 依赖于 DropDownList1

  • SourceUrl

    在没有 idfilter 参数的情况下设置源数据的URL,比如 http://localhost/getLookupHandler.aspx.

  • LookupName

    当前 DropDownList,比如 国家,InvoiceStatus关联的查找列表的标识符。 这里标识符将作为 id 参数在请求中传递,例如:

    http://localhost/getLookupHandler.aspx?id=Country

    它还将用于编写 filter,例如:

    http://localhost/getLookupHandler.aspx?id=State&filter=Country,AU
  • Delimiter

    要单独保存在客户端的隐藏字段中的值的字符。 默认值为'|"'

兼容性

使用 IE 6.Mozilla Firefox 1.04和 Netscape 8.02对该控件进行了测试。

愿望列表

有些工作需要在设计器端完成。 欢迎评论和意见。 如果社区显示出足够的兴趣,我将花更多的时间来改进这个控制。

修订历史

  • 11 2005年07月: 文章和下载文件更新- 现在与 Mozilla Firefox 1.04和 Netscape 8.02兼容。
  • 6 2005年06月: 初始版本。

链接


相关文章