联动下拉菜单是WEB开发中常用到的,基于对增强客户体验,无刷新的要求是很重要的。要实现这个目的,方法有多种,但要实现无刷新无非两种主要方式,一是纯客户端编程。二是采用AJAX技术。下面我就结合自已写的项目代码,总结和比较下两种实现方式:(注:我用的是VS2005+AJAX1.0  C#语言)
         首先先介绍下我用的例子是个省市联动下拉菜单的例子。数据库用的SQL2000,数据库表结构和部分数据如下:


         一、客户端编程
         首先是客户端页面Default1.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default1.aspx.cs" Inherits="Default1" %>

<!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 language=javascript type="text/javascript" src="select.js"></script>
</head>
<body onload="Select('ddlProvince','hidLocation',0)">
    
<form id="form1" runat="server">
        
<div><select name="ddlProvince" id="ddlProvince" onchange="Select('ddlCity','hidLocation',this.value)">
</select>
    省
<select name="ddlCity" id="ddlCity">
</select>
            
<input id="hidLocation" runat="server" type="hidden" /></div>
    
</form>
</body>
</html>
可以看到页面上就两个下拉菜单和一个隐藏域hidLocation。

服务器端文件Default1.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;
using Microsoft.ApplicationBlocks.Data;

public partial class Default1 : System.Web.UI.Page
{
    
protected void Page_Load(object sender, EventArgs e)
    {
        
if (!IsPostBack)
        {
            
string strConn = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
            
string cmdText = "select * from Location";
            
string strContent = "";
            DataTable dt;
            dt 
= SqlHelper.ExecuteDataset(strConn, CommandType.Text, cmdText).Tables[0];
            
foreach (DataRow dr in dt.Rows)
            {
                
for (int i = 0; i < dt.Columns.Count; i++)
                {
                    strContent 
+= dr[i].ToString() + ",";
                }
                strContent 
= strContent.Substring(0, strContent.Length - 1+ "|";
            }

            
if (strContent.Length > 1)
                strContent 
= strContent.Substring(0, strContent.Length - 1);
            hidLocation.Value 
= strContent;
        }
    }
}

这里就只是在第一次加载中,把数据全部读到hidLocation的值中。注:这里我用的是DAAB3.1类库来进行数据操作的。

可以看到,数据源全部读到了客户端,那么在客户端上进行联动下拉菜单的方法就是以下的JS代码:

//定义变量
var array;
var srcid;
//数组排序条件
var i_sort=0;
function n_sort(e1,e2){
   
return(e1[i_sort]-e2[i_sort])
}

function Select(obj,src,filter,k)
{
    
var items=document.getElementById(src).value; 
    
var o=document.getElementById(obj);
    
if(srcid!=src){
        
// 加载数据到数组中
        var ary = new Array();       
        
var piArray = items.split("|");
        
for(var i=0; i<piArray.length; i++)
        {   
            
var tmp = piArray[i].toString().split(",");
            ary[i]
=tmp;
        }
        array 
= ary;
        srcid 
= src;
    }
    
//排序
    if(k!=null){
        i_sort
=k;
        array.sort(n_sort);
    }
    
//清除下拉项
    for(var i=o.length-1;i>=0;i--){
        o.removeChild(o.options[i]);
    }
    
//生成下拉项
    for(var i=0;i<array.length;i++){
        
if(filter!=null){
            
if(array[i][2== filter){
                o.options[o.length] 
= new Option(array[i][1], array[i][0]);
            }
        }
else{
            o.options[o.length] 
= new Option(array[i][1], array[i][0]);
        }
    }
    o.selectedIndex 
= 0;
}

      二、AJAX方法:
      用AJAX方法,就是采用异步回发的方法来使联动下拉控件绑定不同的数据源。那么用AJAX的方法很多,可以自已用Javascript写HttpRequset等,也可用JQuery,在这里我是 用AJAX 1.0组件可以非常快捷的做到这一点。只用鼠标拖拖点点就OK了,当然在这之前得要装上AJAX1.0,并配好web.config文件。
      第一步,拖一个ScriptManager和UpdatePanel。再拖两个下拉控件,用智能标记绑定和配好各自的数据源,原代码如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    
<title>Untitled Page</title>
</head>
<body>
    
<form id="form1" runat="server">
        
<asp:ScriptManager ID="ScriptManager1" runat="server" />
        
<div>
            
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
                
<ContentTemplate>
                    
<asp:DropDownList ID="ddlProvince" runat="server" AutoPostBack="True" DataSourceID="SqlDataSource1"
                        DataTextField
="LocationName" DataValueField="Id">
                    
</asp:DropDownList>
                    省
<asp:DropDownList ID="ddlCity" runat="server" DataSourceID="SqlDataSource2" DataTextField="LocationName"
                        DataValueField
="Id">
                    
</asp:DropDownList><asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
                        SelectCommand
="SELECT [Id], [LocationName] FROM [Location] WHERE ([ParentId] = @ParentId)">
                        
<SelectParameters>
                            
<asp:ControlParameter ControlID="ddlProvince" Name="ParentId" PropertyName="SelectedValue"
                                Type
="Int32" />
                        
</SelectParameters>
                    
</asp:SqlDataSource>
                    市
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
                        SelectCommand
="SELECT [Id], [LocationName] FROM [Location] WHERE ([ParentId] = @ParentId)">
                        
<SelectParameters>
                            
<asp:Parameter DefaultValue="0" Name="ParentId" Type="Int32" />
                        
</SelectParameters>
                    
</asp:SqlDataSource>
                
</ContentTemplate>
            
</asp:UpdatePanel>
        
</div>
    
</form>
</body>
</html>

OK了!当然不配数据源,用编程的方式写代码也一样,关键是看各自项目的需要和架构。

            这两种方式各有优缺点。第一种纯客户端方式,在选择菜单时,并没有请求服务器,完全是在客户端运行,所以对提高网站性能和减少数据访问是个不错的选择。但它是第一次将所有数据全发送到客户端,页面加载会慢些。也就是说如果一个数据量大的话,这种方式并不适合。第二种方式,优缺点正好和第一种方式相对,每次加载回发数据量都不大,但它每次选择其实就是向服务器发送了一次请求。所以采用哪种方式,视具体情况而定,也可搭配使用。
posted on 2007-08-07 16:07  刘伟(xiaoss)  阅读(1751)  评论(0编辑  收藏  举报