您的位置:首页 > 其它

无刷新的四级联动下拉框实例(AjaxPro)

2007-06-29 19:06 465 查看
之前的“省市县镇”四级控件是使用 MagicAjax 开发的。每一级都是到数据库中读取。经过 DBA 分析,
和该控件有关的表查询量很大, SQL 语句解析次数也非常多,虽然是 Oracle 数据库还是要尽量避免的。
为此新的控件将“省市”两级的数据存放在 JS 里,而“县镇”两级从数据库中读取,同时再结合项目需
要的特殊功能。

主要功能:
用户访问网站,首先根据二级域名加载用户所在的地区(如 http://xm.XXXX.com 福建-厦门)。如果没
有二级域名,那么根据 Cookie (如果之前访问过)加载用户所在的地区。如果没有,最后根据 IP 来
加载用户所在的地区。
如果是通过 Cookie 或是 IP 来判断,最后还要进行重定向(就是将 http://www.XXXX.com 转成
http://bj.XXXX.com)。如果是根据 IP 判断的,还要把用户所在的地区存入 Cookie。方便下次使用。
为了能从数据库读取数据,直接加载相应地区,还有能从下拉框中读取用户选择的地区就自定义一些属性。

特殊功能
是否重定向、是否只显示“省市”两级、是否垂直排列下拉框(默认是横向)、是否在在省份下拉框前
显示“省份”,城市下拉框前显示“城市”......、是否禁用控件(有些情况下,你可能要禁止用户选
择,等满足条件后才能选)

其他说明
前台脚本采用 JavaScript 和 DOM 互操作,全部使用 W3C 标准使其在各种浏览器下都正常。操作
<select> 采用更通用的 createElement() 而没有使用 options.add()。
后台采用 ASP.NET 进行少量操作(保存 Cookie||读数据库)
前后台采用 AjaxPro 使 JavaScript 和 C# 交互(传递枚举||调用方法||传递结果集)这部分应该是
重点....脚本和高级语言的交互是很让人向往的...暂时只会第三方 Ajax
最后采用一些看似多余的调用,实际上是为了防止 AjaxPro 生成的代码泄露了程序集和命名空间,老
大要求的...

顺便说下,如果数据库设计合理,前两位省份,中间两位城市,最后两位县/区,那么程序中很多地方
的代码都能省了...可见良好的数据库设计是非常重要的。

项目请一定要采用 AjaxPro 6.10.4.1 版本,其他版本有 BUG ,我也是开发中被搞乱了
下面就是源码了,没什么好说了...注释都很详细了

首先是 AreaInfo.cs 地区信息实体类,方便在其他程序读取用的


namespace AreaDropDownList




...{




/**//// <summary>


/// 地区信息类


/// </summary>


public sealed class AreaInfo




...{


private int _SFID;


private int _CSID;


private int _XianID;


private int _ZhenID;




private string _SF;


private string _CS;


private string _Xian;


private string _Zhen;




private string _Domain;






/**//// <summary>


/// 省份ID


/// </summary>


public int SFID




...{




get ...{ return this._SFID; }




set ...{ this._SFID = value; }


}




/**//// <summary>


/// 城市ID


/// </summary>


public int CSID




...{




get ...{ return this._CSID; }




set ...{ this._CSID = value; }


}




/**//// <summary>


/// 县/区ID


/// </summary>


public int XianID




...{




get ...{ return this._XianID; }




set ...{ this._XianID = value; }


}




/**//// <summary>


/// 镇


/// </summary>


public int ZhenID




...{




get ...{ return this._ZhenID; }




set ...{ this._ZhenID = value; }


}






/**//// <summary>


/// 省份名称


/// </summary>


public string SF




...{




get ...{ return this._SF; }




set ...{ this._SF = value; }


}




/**//// <summary>


/// 城市名称


/// </summary>


public string CS




...{




get ...{ return this._CS; }




set ...{ this._CS = value; }


}




/**//// <summary>


/// 县/区名称


/// </summary>


public string Xian




...{




get ...{ return this._Xian; }




set ...{ this._Xian = value; }


}




/**//// <summary>


/// 镇名称


/// </summary>


public string Zhen




...{




get ...{ return this._Zhen; }




set ...{ this._Zhen = value; }


}






/**//// <summary>


/// 域名


/// </summary>


public string Domain




...{




get ...{ return this._Domain; }




set ...{ this._Domain = value; }


}


}


}

接下来是数据访问层,项目使用的是 Oracle


using System;


using System.Data;


using System.Data.OracleClient;


using System.Web;




namespace AreaDropDownList




...{




/**//// <summary>


/// 地区控件数据访问操作层


/// </summary>


public static class AreaDAL




...{


private static readonly string Link = "server=gou200;user=gou;pwd=gou;";
private static readonly string[] SecondDomain = new string[] ...{ "www", "gou", "un", "help", "hotel", "news", "trip", "brand", "soft", "train" };
private static readonly int CookieDay = 3; //Cookie 保存的天数


private static readonly string CookieDomain = "xxx.cn"; //Cookie 的域






/**//// <summary>


/// 返回符合 SQL语句 的 DataTable


/// </summary>


/// <param name="sql">SQL 语句</param>


/// <returns></returns>


public static DataTable GetDataTable(string sql)




...{


OracleConnection conn = new OracleConnection(Link);


OracleDataAdapter adapter = new OracleDataAdapter(sql, conn);


DataTable table = new DataTable();


adapter.Fill(table);


return table;


}






/**//// <summary>


/// 将当前所有下拉框的值存入 Cookie


/// </summary>


/// <param name="sfid">省份ID</param>


/// <param name="csid">城市ID</param>


/// <param name="xianid">县/区ID</param>


/// <param name="zhenid">镇ID</param>


/// <param name="sf">省份名</param>


/// <param name="cs">城市名</param>


/// <param name="xian">县/区名</param>


/// <param name="zhen">镇名</param>


/// <param name="domain">地区域名</param>


public static void SaveCookie(int sfid, int csid, int xianid, int zhenid, string sf, string cs, string xian, string zhen, string domain)




...{


HttpCookie cookie = new HttpCookie("Area");


cookie["SFID"] = sfid.ToString();


cookie["CSID"] = csid.ToString();


cookie["XianID"] = xianid.ToString();


cookie["ZhenID"] = zhenid.ToString();


cookie["SF"] = HttpContext.Current.Server.UrlEncode(String.IsNullOrEmpty(sf) ? "" : sf.Replace("—请选择—", ""));


cookie["CS"] = HttpContext.Current.Server.UrlEncode(String.IsNullOrEmpty(cs) ? "" : cs.Replace("—请选择—", ""));


cookie["Xian"] = HttpContext.Current.Server.UrlEncode(String.IsNullOrEmpty(xian) ? "" : xian.Replace("—请选择—", ""));


cookie["Zhen"] = HttpContext.Current.Server.UrlEncode(String.IsNullOrEmpty(zhen) ? "" : zhen.Replace("—请选择—", ""));


cookie["Domain"] = domain;


cookie.Domain = CookieDomain;


cookie.Expires = DateTime.Now.AddDays(CookieDay);


HttpContext.Current.Response.Cookies.Add(cookie);


}






/**//// <summary>


/// 将地区信息存入 Cookie


/// </summary>


/// <param name="ai">地区信息</param>


private static void SaveCookie(AreaInfo ai)




...{


SaveCookie(ai.SFID, ai.CSID, ai.XianID, ai.ZhenID, ai.SF, ai.CS, ai.Xian, ai.Zhen, ai.Domain);


}






/**//*=====================================================================*/






/**//// <summary>


/// 通过 域名 加载相应的地区


/// </summary>


/// <returns></returns>


public static AreaInfo GetAreaInfoByDomain()




...{


string domain = HttpContext.Current.Request.Url.Host.Split('.')[0].ToLower();


if (IsSecondDomain(domain))


return null;




AreaInfo ai;


HttpCookie cookie = HttpContext.Current.Request.Cookies["Area"];


if (cookie != null && cookie["Domain"] == domain)




...{


//Cookie 里的域名和当前的域名相同,说明 Cookie 里有更详细的地区信息(如:从 Cookie 重定向而来)


ai = new AreaInfo();


ai.SFID = Convert.ToInt32(cookie["SFID"]);


ai.CSID = Convert.ToInt32(cookie["CSID"]);


ai.XianID = Convert.ToInt32(cookie["XianID"]);


ai.ZhenID = Convert.ToInt32(cookie["ZhenID"]);


ai.SF = HttpContext.Current.Server.UrlDecode(cookie["SF"]);


ai.CS = HttpContext.Current.Server.UrlDecode(cookie["CS"]);


ai.Xian = HttpContext.Current.Server.UrlDecode(cookie["Xian"]);


ai.Zhen = HttpContext.Current.Server.UrlDecode(cookie["Zhen"]);


ai.Domain = cookie["Domain"];


}


else




...{


ai = GetAreaInfoByDomain(domain);


if (ai == null)


return null;


SaveCookie(ai);


}




return ai;


}






/**//// <summary>


/// 返回域名对应的地区信息


/// </summary>


/// <param name="domain">三级域名</param>


/// <returns></returns>


private static AreaInfo GetAreaInfoByDomain(string domain)




...{


OracleConnection conn = new OracleConnection(Link);


//使用一条SQL 代替 多次SQL查询


string sql = String.Format("SELECT cs.csid,(cs.sfid || sf.sfid) AS sfid,cs.CityName,(cs.sfname || sf.sfname) AS sfname FROM (SELECT c.pkid AS csid,c.OneID AS sfid,c.CityName AS CityName,s.sfname AS sfname FROM (SELECT PKID,OneID,CityName FROM CityInfo WHERE CityDomain='{0}') c RIGHT JOIN(SELECT pkid,CityName AS sfname FROM CityInfo WHERE pkid=(SELECT OneID FROM CityInfo WHERE CityDomain='{0}')) s ON c.oneid=s.pkid) cs FULL OUTER JOIN (SELECT pkid AS sfid,CityName AS sfname FROM cityinfo WHERE citydomain='{0}' AND OneID=0) sf ON cs.sfid=sf.sfid", domain);


OracleCommand cmd = new OracleCommand(sql, conn);


conn.Open();


OracleDataReader dr = cmd.ExecuteReader();


if (dr.Read())




...{


AreaInfo ai = new AreaInfo();


Object[] os = new object[dr.FieldCount];


dr.GetValues(os);


dr.Close();


conn.Close();


ai.CSID = (os[0] is DBNull) ? 0 : Convert.ToInt32(os[0]);


ai.SFID = (os[1] is DBNull) ? 0 : Convert.ToInt32(os[1]);


ai.CS = (os[2] is DBNull) ? String.Empty : os[2].ToString();


ai.SF = (os[3] is DBNull) ? String.Empty : os[3].ToString();


ai.Domain = domain;


return ai;


}


dr.Close();


conn.Close();


return null;


}






/**//// <summary>


/// 是否是二级域名


/// </summary>


/// <param name="domain">可能是二级域名的字符串</param>


/// <returns>是,返回 ture</returns>


private static bool IsSecondDomain(string domain)




...{


foreach (string sd in SecondDomain)




...{


if (domain == sd)


return true;


}


return false;


}






/**//*=====================================================================*/






/**//// <summary>


/// 返回 Cookie 对应的地区信息


/// </summary>


/// <returns></returns>


public static AreaInfo GetAreaInfoByCookie()




...{


AreaInfo ai = new AreaInfo();


HttpCookie cookie = HttpContext.Current.Request.Cookies["Area"];


if (cookie == null)


return null;




ai.SFID = Convert.ToInt32(cookie["SFID"]);


ai.CSID = Convert.ToInt32(cookie["CSID"]);


ai.XianID = Convert.ToInt32(cookie["XianID"]);


ai.ZhenID = Convert.ToInt32(cookie["ZhenID"]);


ai.SF = HttpContext.Current.Server.UrlDecode(cookie["SF"]);


ai.CS = HttpContext.Current.Server.UrlDecode(cookie["CS"]);


ai.Xian = HttpContext.Current.Server.UrlDecode(cookie["Xian"]);


ai.Zhen = HttpContext.Current.Server.UrlDecode(cookie["Zhen"]);


ai.Domain = cookie["Domain"];




if (ai.SFID == 0)


return null;




return ai;


}






/**//*=====================================================================*/






/**//// <summary>


/// 通过 IP 加载相应的地区


/// </summary>


/// <returns></returns>


public static AreaInfo GetAreaInfoByIP()




...{


AreaInfo ai = GetAreaInfoByIP(HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]);


if (ai == null)


return null;


SaveCookie(ai);


return ai;


}






/**//// <summary>


/// 返回 IP 对应的地区信息


/// </summary>


/// <param name="ip">IP字符串</param>


/// <returns></returns>


private static AreaInfo GetAreaInfoByIP(string ip)




...{


AreaInfo ai = new AreaInfo();


uint IpNum;


string[] IPList = ip.Split('.');


IpNum = Convert.ToUInt32(Convert.ToUInt32(IPList[0]) * 255 * 255 * 255 + Convert.ToUInt32(IPList[1]) * 255 * 255 + Convert.ToUInt32(IPList[2]) * 255 + Convert.ToUInt32(IPList[3]));


string sql = String.Format("SELECT i.sfid00,i.CityCode,i.sfname,i.CityName,c.CityDomain FROM (SELECT CityDomain,pkid FROM CityInfo) c RIGHT JOIN (SELECT SFID00,CityCode,SFName,CityName FROM T_BM_Ip WHERE IpOne<={0} AND IpTwo>={0}) i ON c.pkid=i.CityCode", IpNum);


OracleConnection conn = new OracleConnection(Link);


OracleCommand cmd = new OracleCommand(sql, conn);


conn.Open();


OracleDataReader dr = cmd.ExecuteReader();


if (dr.Read())




...{


Object[] os = new object[dr.FieldCount];


dr.GetValues(os);


dr.Close();


conn.Close();


ai.SFID = (os[0] is DBNull) ? 0 : Convert.ToInt32(os[0]);


ai.CSID = (os[1] is DBNull) ? 0 : Convert.ToInt32(os[1]);


ai.SF = (os[2] is DBNull) ? String.Empty : os[2].ToString();


ai.CS = (os[3] is DBNull) ? String.Empty : os[3].ToString();


ai.Domain = (os[4] is DBNull) ? String.Empty : os[4].ToString();


return ai;


}


dr.Close();


conn.Close();


ai.SFID = 11; //设置默认值


ai.SF = "北京";


ai.Domain = "bj";


return ai;


}


}


}







然后就是重点了...用户控件 前台代码,中间有段很长的 省份城市JS 数组,我去掉了,想看可以去另一篇同名 blog 看


<%@ Control Language="C#" AutoEventWireup="true" CodeFile="AreaControl.ascx.cs" Inherits="AreaControl" %>


<div>


<table id="AreaTable" runat="server">


<tr>


<td>


<select id="sSF" runat="server">


<option selected="selected" value="0">—请选择—</option>


</select>


</td>


<td>


<select id="sCS" runat="server">


<option selected="selected" value="0">—请选择—</option>


</select>


</td>


<td>


<select id="sXian" runat="server">


<option selected="selected" value="0">—请选择—</option>


</select>


</td>


<td>


<select id="sZhen" runat="server">


<option selected="selected" value="0">—请选择—</option>


</select>


</td>


</tr>


</table>


<input type="hidden" id="hSF" runat="server" />


<input type="hidden" id="hCS" runat="server" />


<input type="hidden" id="hXian" runat="server" />


<input type="hidden" id="hZhen" runat="server" />


<input type="hidden" id="hDomain" runat="server" />


</div>




<script type="text/javascript">


//<%-- ID 城市 上级ID 二级域名--%>


var aDQ=new Array();


//<%-- 省份的上级ID改为 -1 和 "—请选择—" 区分开 --%>


aDQ[0]=["11","北京","-1","bj"];


//该数组请去另一篇 Blog 看




//<%-- 通过 DOM 创建下拉框 --%>


//<%-- obj:下拉框的 options 数据集 --%>


//<%-- id:下拉框的 id --%>


function CreateDropDownList(obj,id)




...{


var sel=document.getElementById(id);


if(sel==null) //<%-- 可能只显示省市 --%>


return;


sel.options.length=1; //<%-- 保存"—请选择—" --%>


//<%-- 对于省份、城市常用 Array 存储,对于县、镇则从数据库读取 --%>


if(obj==null)


return;


if(obj instanceof Array)




...{


for(var i=0;i<obj.length;i++)




...{


var op=document.createElement("option");


op.setAttribute("value",obj[i][0]); //<%-- 可考虑改成 value="xm,厦门">厦门 --%>


var txt=document.createTextNode(obj[i][1]);


op.appendChild(txt);


sel.appendChild(op);


}


}


else




...{


for(var i=0;i<obj.Rows.length;i++) //<%-- 注意这里是 length 不是 Count --%>




...{


var op=document.createElement("option");


op.setAttribute("value",obj.Rows[i].ID); //<%-- 注意区分大小写 --%>


var txt=document.createTextNode(obj.Rows[i].NAME); //<%-- 根 DataTable 的列名称要一致 --%>


op.appendChild(txt);


sel.appendChild(op);


}


}


//<%-- 绑定下一个下拉框 --%>


switch(id)




...{


//<%-- 选择一次,保存到 Cookie 一次,可以往 onchange 事件里加入 Save(); --%>




case "<%=this.sSF.ClientID%>":sel.onchange=function()...{ClearXianZhen();CreateDropDownList(GetArray(this.value),"<%=this.sCS.ClientID%>");Save();};break;




case "<%=this.sCS.ClientID%>":sel.onchange=function()...{ClearZhen();CreateDropDownList(AreaControl.GetDataTable(this.value,AreaEnum.Xian).value,"<%=this.sXian.ClientID%>");Save();};break; //<%-- JS 向 C# 传递参数,并取得 C# 的返回值 --%>




case "<%=this.sXian.ClientID%>":sel.onchange=function()...{CreateDropDownList(AreaControl.GetDataTable(this.value,AreaEnum.Zhen).value,"<%=this.sZhen.ClientID%>");Save();};break; //<%-- 返回值.value --%>




default:sel.onchange=function()...{Save();};break; //alert(this.value);


}


}


//<%-- 获取要求的数组 --%>


//<%-- val:所属的省份ID --%>


function GetArray(val)




...{


if(val==0) //<%-- 用户选"—请选择—"不查询 --%>


return null;


var temp=new Array();


var j=0;


for(var i=0;i<aDQ.length;i++)




...{


if(val==aDQ[i][2].toString())




...{


temp[j]=aDQ[i];


j++;


}


}


return temp;


}


//<%-- 清空"镇"下拉框 --%>


function ClearZhen()




...{


CreateDropDownList(null,"<%=this.sZhen.ClientID%>");


}


//<%-- 清空"县"和"镇"下拉框 --%>


function ClearXianZhen()




...{


CreateDropDownList(null,"<%=this.sXian.ClientID%>");


CreateDropDownList(null,"<%=this.sZhen.ClientID%>");


}




//<%-- 将当前所有下拉框的值存入 Cookie --%>


function Save()




...{


var sf=Single("<%=this.sSF.ClientID%>","<%=this.hSF.ClientID%>");


var cs=Single("<%=this.sCS.ClientID%>","<%=this.hCS.ClientID%>");


var xian=Single("<%=this.sXian.ClientID%>","<%=this.hXian.ClientID%>");


var zhen=Single("<%=this.sZhen.ClientID%>","<%=this.hZhen.ClientID%>");




var domain=GetDomain((cs.ID==0)?sf.ID:cs.ID);


document.getElementById("<%=this.hDomain.ClientID%>").value=domain;


//<%-- 暂时不存 Cookie ,只存到隐藏控件里 --%>


//<%-- AreaControl.SaveCookie(sf.ID,cs.ID,xian.ID,zhen.ID,sf.Name,cs.Name,xian.Name,zhen.Name,domain); --%>


}


//<%-- 返回单个下拉框的值和文本 --%>


//<%-- sid:下拉框ID --%>


//<%-- hid:隐藏控件ID --%>


function Single(sid,hid)




...{


var sel=document.getElementById(sid);


var a=new Area();


if(sel==null) //<%-- 可能只显示省市 --%>


return a;


a.ID=sel.value; //<%-- 取得下拉框的 value --%>


a.Name=sel.options[sel.selectedIndex].text; //<%-- 取得下拉框的 text --%>


document.getElementById(hid).value=a.Name; //<%-- text 另存到隐藏控件里 --%>


return a;


}


//<%-- 构造函数 --%>


function Area()




...{


this.ID; //<%-- 下拉框的值 --%>


this.Name; //<%-- 下拉框的文本 --%>


}


//<%-- 返回 ID 对应的域名 --%>


//<%-- id:地区ID --%>


function GetDomain(id)




...{


for(var i=0;i<aDQ.length;i++)




...{


if(aDQ[i][0]==id)


return aDQ[i][3];


}


return "";


}




/**//*<%------------------------------------------------------------------%>*/


//<%-- 通过 域名 加载相应的地区 --%>


function LoadAreaByDomain()




...{


var ai=AreaControl.GetAreaInfoByDomain().value;


if(ai==null)


return false;




Bind(ai);


return true;


}


//<%-- 根据地区信息绑定相应的下拉框 --%>


//<%-- ai:地区信息类 --%>


function Bind(ai)




...{


bind(ai.SFID,ai.CSID,ai.XianID,ai.ZhenID);


}


//<%-- 根据地区信息绑定相应的下拉框 --%>


//<%-- 因为JS不支持重载写成2个方法 --%>


function bind(sfid,csid,xianid,zhenid)




...{


var index;


if(sfid!=0)




...{


index=Val2Index(sfid,"<%=this.sSF.ClientID%>");


document.getElementById("<%=this.sSF.ClientID%>").selectedIndex=index;


document.getElementById("<%=this.hSF.ClientID%>").value=Index2Text(index,"<%=this.sSF.ClientID%>"); //<%-- text 另存到隐藏控件里 --%>


CreateDropDownList(GetArray(sfid.toString()),"<%=this.sCS.ClientID%>");


}


if(csid!=0)




...{


index=Val2Index(csid,"<%=this.sCS.ClientID%>");


document.getElementById("<%=this.sCS.ClientID%>").selectedIndex=index;


document.getElementById("<%=this.hCS.ClientID%>").value=Index2Text(index,"<%=this.sCS.ClientID%>");


CreateDropDownList(AreaControl.GetDataTable(csid.toString(),AreaEnum.Xian).value,"<%=this.sXian.ClientID%>") //<%-- 要把 int 型的转换成字符串--%>


}


if(xianid!=0 && document.getElementById("<%=this.sXian.ClientID%>")!=null) //<%-- 可能只显示省市 --%>




...{


index=Val2Index(xianid,"<%=this.sXian.ClientID%>");


document.getElementById("<%=this.sXian.ClientID%>").selectedIndex=index;


document.getElementById("<%=this.hXian.ClientID%>").value=Index2Text(index,"<%=this.sXian.ClientID%>");


CreateDropDownList(AreaControl.GetDataTable(xianid.toString(),AreaEnum.Zhen).value,"<%=this.sZhen.ClientID%>");


}


if(zhenid!=0 && document.getElementById("<%=this.sZhen.ClientID%>")!=null)




...{


index=Val2Index(zhenid,"<%=this.sZhen.ClientID%>");


document.getElementById("<%=this.sZhen.ClientID%>").selectedIndex=index;


document.getElementById("<%=this.hZhen.ClientID%>").value=Index2Text(index,"<%=this.sZhen.ClientID%>");


}




document.getElementById("<%=this.hDomain.ClientID%>").value=GetDomain((csid==0)?sfid:csid);


}


//<%-- 将 <select> 的 value 换算成 selectedIndex --%>


//<%-- val:下拉框的值 --%>


//<%-- id:下拉框 ID --%>


function Val2Index(val,id)




...{


var sel=document.getElementById(id);


for(var i=0;i<sel.options.length;i++)




...{


if(val==sel.options[i].value)


return i;


}


return 0;


}


//<%-- 将 <select> 的 value 换算成 text --%>


//<%-- index:下拉框的值 --%>


//<%-- id:下拉框 ID --%>


function Index2Text(index,id)




...{


return document.getElementById(id).options[index].text;


}




/**//*<%------------------------------------------------------------------%>*/


//<%-- 通过 cookie 加载相应的地区 --%>


function LoadAreaByCookie()




...{


var ai=AreaControl.GetAreaInfoByCookie().value;


if(ai==null)


return false;




//<%-- 根据地区域名重定向 --%>


if(<%=this.IsRedirect.ToString().ToLower()%> && ai.Domain!=null && ai.Domain!="" && ai.Domain!=window.location.hostname.split(".")[0])




...{


window.location.href=window.location.href.substring(0,7)+ai.Domain+"."+window.location.href.slice(7);


return true; //<%-- 返回真,不执行后面的判断,直接页面重定向 --%>


}




Bind(ai);


return true;


}




/**//*<%------------------------------------------------------------------%>*/


//<%-- 通过 IP 加载相应的地区 --%>


function LoadAreaByIP()




...{


var ai=AreaControl.GetAreaInfoByIP().value;


if(ai==null)


return false;




if(<%=this.IsRedirect.ToString().ToLower()%> && ai.Domain!=null && ai.Domain!="" && ai.Domain!=window.location.hostname.split(".")[0])




...{


window.location.href=window.location.href.substring(0,7)+ai.Domain+"."+window.location.href.slice(7);


return true;


}




Bind(ai);


return true;


}




/**//*<%------------------------------------------------------------------%>*/


//<%-- 执行入口 --%>


var arr=GetArray("-1");


CreateDropDownList(arr,"<%=this.sSF.ClientID%>");




//<%-- 是否只显示省份和城市 --%>


if(<%=this.OnlySFCS.ToString().ToLower()%>) //<%-- JS 的布尔值是小写 --%>




...{


var table=document.getElementById("<%=this.AreaTable.ClientID%>");


table.rows[0].deleteCell(3); //<%-- 删除后行索引变小,因此要从后面开始删除 --%>


table.rows[0].deleteCell(2);


}




if(<%=this.SFID%>==0) //<%-- 没赋值才根据 域名->Cookie->IP 绑定下拉框 --%>


(LoadAreaByDomain()) ? "" : ((LoadAreaByCookie()) ? "" : LoadAreaByIP());


else //<%-- 只要省份有值就绑定 --%>


bind(<%=this.SFID%>,<%=this.CSID%>,<%=this.XianID%>,<%=this.ZhenID%>); //<%-- 赋值绑定 --%>




//<%-- 是否垂直显示 --%>


if(<%=this.IsVertical.ToString().ToLower()%>)




...{


var h=document.getElementById("<%=this.AreaTable.ClientID%>");


var v=document.createElement("table");


v.setAttribute("id","<%=this.AreaTable.ClientID%>");




InsertRow(h.rows[0].cells.length);




h.parentNode.replaceChild(v,h); //<%-- 注意这里要通过添加 <div> 来解决 ascx 不能操作 aspx 的问题 --%>


}


//<%-- 循环创建(将列变成行) --%>


//<%-- length:循环次数 --%>


function InsertRow(length)




...{


for(var i=0;i<length;i++)




...{


v.insertRow(i);


v.rows[i].insertCell(0);


v.rows[i].cells[0].appendChild(h.rows[0].cells[i].childNodes[0]); //<%-- 将 cell 的的元素剪贴走 --%>


}


}




//<%-- 是否显示在下拉框前显示名称(省份、城市、县、镇) --%>


if(<%=this.IsDisplayName.ToString().ToLower()%>)




...{


var sel=document.getElementById("<%=this.sSF.ClientID%>");


sel.parentNode.insertBefore(document.createTextNode("省份:"),sel);




sel=document.getElementById("<%=this.sCS.ClientID%>");


sel.parentNode.insertBefore(document.createTextNode("城市:"),sel);




sel=document.getElementById("<%=this.sXian.ClientID%>");


if(sel!=null)


sel.parentNode.insertBefore(document.createTextNode("县区:"),sel);




sel=document.getElementById("<%=this.sZhen.ClientID%>");


if(sel!=null)


sel.parentNode.insertBefore(document.createTextNode("乡镇:"),sel);


}




//<%-- 是否禁用控件 --%>


if(<%=this.IsDisabled.ToString().ToLower()%>)




...{


var sels=document.getElementById("<%=this.AreaTable.ClientID%>").getElementsByTagName("select");


for(var i=0;i<sels.length;i++)


sels[i].setAttribute("disabled","disabled");


}


</script>

最后就是用户控件的后台页了.


using System;


using System.Data;


using System.Data.OracleClient;


using System.Web.UI.MobileControls;


using AreaDropDownList;




public partial class AreaControl : System.Web.UI.UserControl




...{




属性#region 属性


private int _SFID;


private int _CSID;


private int _XianID;


private int _ZhenID;


private string _SF;


private string _CS;


private string _Xian;


private string _Zhen;


private string _Domain;


private bool _OnlySFCS;


private bool _IsRedirect;


private bool _IsVertical;


private bool _IsDisplayName;


private bool _IsDisabled;




//地区ID


public int SFID




...{




get ...{ return this._SFID; }




set ...{ this._SFID = value; }


}


public int CSID




...{




get ...{ return this._CSID; }




set ...{ this._CSID = value; }


}


public int XianID




...{




get ...{ return this._XianID; }




set ...{ this._XianID = value; }


}


public int ZhenID




...{




get ...{ return this._ZhenID; }




set ...{ this._ZhenID = value; }


}




//地区名


public string SF




...{




get ...{ return this._SF; }




set ...{ this._SF = value; }


}


public string CS




...{




get ...{ return this._CS; }




set ...{ this._CS = value; }


}


public string Xian




...{




get ...{ return this._Xian; }




set ...{ this._Xian = value; }


}


public string Zhen




...{




get ...{ return this._Zhen; }




set ...{ this._Zhen = value; }


}




//地区域名


public string Domain




...{




get ...{ return this._Domain; }




set ...{ this._Domain = value; }


}




/**//************** 特殊属性 ****************/


//是否重定向(通过 Cookie 和 IP 绑定下拉框会重定向)


public bool IsRedirect




...{




get ...{ return this._IsRedirect; }




set ...{ this._IsRedirect = value; }


}


//只显示省份城市


public bool OnlySFCS




...{




get ...{ return this._OnlySFCS; }




set ...{ this._OnlySFCS = value; }


}


//是否垂直显示


public bool IsVertical




...{




get ...{ return this._IsVertical; }




set ...{ this._IsVertical = value; }


}


//是否显示在下拉框前显示名称(省份、城市、县、镇)


public bool IsDisplayName




...{




get ...{ return this._IsDisplayName; }




set ...{ this._IsDisplayName = value; }


}


//是否禁用控件


public bool IsDisabled




...{




get ...{ return this._IsDisabled; }




set ...{ this._IsDisabled = value; }


}


#endregion




//在 aspx 取值用(赋值用 JS)


protected void Page_Init()




...{


//为了在 aspx 页面的 按钮事件里取值


if (this.IsPostBack)




...{


this.SFID = Convert.ToInt32(this.Request.Form[this.sSF.UniqueID]);


this.CSID = Convert.ToInt32(this.Request.Form[this.sCS.UniqueID]);


this.XianID = Convert.ToInt32(this.Request.Form[this.sXian.UniqueID]);


this.ZhenID = Convert.ToInt32(this.Request.Form[this.sZhen.UniqueID]);


this.SF = this.Request.Form[this.hSF.UniqueID].Replace("—请选择—", "");


this.CS = this.Request.Form[this.hCS.UniqueID].Replace("—请选择—", "");


this.Xian = this.Request.Form[this.hXian.UniqueID].Replace("—请选择—", "");


this.Zhen = this.Request.Form[this.hZhen.UniqueID].Replace("—请选择—", "");


this.Domain = this.Request.Form[this.hDomain.UniqueID];


}


}




protected void Page_Load(object sender, EventArgs e)




...{


//将C#的类和枚举分别注册到JS里


AjaxPro.Utility.RegisterTypeForAjax(typeof(AreaControl));


AjaxPro.Utility.RegisterEnumForAjax(typeof(AreaEnum));


}






/**//// <summary>


/// 将当前下拉框对应的地区信息存入 Cookie(供"保存"按钮使用)


/// </summary>


public void SaveCookie()




...{


AreaDAL.SaveCookie(this.SFID, this.CSID, this.XianID, this.ZhenID, this.SF, this.CS, this.Xian, this.Zhen, this.Domain);


}






/**//*====================== 以下是为防止命名空间暴露在 JS 里 ==========================*/






/**//// <summary>


/// 取得下拉框所需数据


/// </summary>


/// <param name="UpID">上一级ID</param>


/// <param name="ae">县/镇</param>


/// <returns>返回 DataTable</returns>


[AjaxPro.AjaxMethod]


public static DataTable GetDataTable(string UpID, AreaEnum ae)




...{


if (UpID == "0" || String.IsNullOrEmpty(UpID)) //用户选"—请选择—"不查询


return null;




//处于安全性考虑采用 列别名


//Oracle 返回的 DataTable 里的列名全是大写,在页面取值时记得大写


string sql;


if (Enum.Equals(ae, AreaEnum.Xian))


sql = "SELECT PKID AS id,CityName AS name,OneID,CityDomain FROM CityInfo WHERE THREEID=0 AND TWOID=" + UpID;


else


sql = "SELECT PKID AS id,CityName AS name,OneID,CityDomain FROM CityInfo WHERE THREEID=" + UpID;




return AreaDAL.GetDataTable(sql);


}






/**//// <summary>


/// 将当前所有下拉框的值存入 Cookie


/// </summary>


/// <param name="sfid">省份ID</param>


/// <param name="csid">城市ID</param>


/// <param name="xianid">县/区ID</param>


/// <param name="zhenid">镇ID</param>


/// <param name="sf">省份名</param>


/// <param name="cs">城市名</param>


/// <param name="xian">县/区名</param>


/// <param name="zhen">镇名</param>


/// <param name="domain">地区域名</param>


[AjaxPro.AjaxMethod]


public static void SaveCookie(int sfid, int csid, int xianid, int zhenid, string sf, string cs, string xian, string zhen, string domain)




...{


AreaDAL.SaveCookie(sfid, csid, xianid, zhenid, sf, cs, xian, zhen, domain);


}






/**//*=====================================================================*/






/**//// <summary>


/// 通过 域名 加载相应的地区


/// </summary>


/// <returns></returns>


[AjaxPro.AjaxMethod]


public static AreaInfo GetAreaInfoByDomain()




...{


return AreaDAL.GetAreaInfoByDomain();


}






/**//*=====================================================================*/






/**//// <summary>


/// 返回 Cookie 对应的地区信息


/// </summary>


/// <returns></returns>


[AjaxPro.AjaxMethod]


public static AreaInfo GetAreaInfoByCookie()




...{


return AreaDAL.GetAreaInfoByCookie();


}






/**//*=====================================================================*/






/**//// <summary>


/// 通过 IP 加载相应的地区


/// </summary>


/// <returns></returns>


[AjaxPro.AjaxMethod]


public static AreaInfo GetAreaInfoByIP()




...{


return AreaDAL.GetAreaInfoByIP();


}




}






/**//// <summary>


/// 地区枚举(如果数据库设计合理,前两位省份,中间两位城市,最后两位县/区,那么就不需要这个枚举,代码量也少很多)


/// </summary>


public enum AreaEnum




...{




/**//// <summary>


/// 省


/// </summary>


SF,




/**//// <summary>


/// 市


/// </summary>


CS,




/**//// <summary>


/// 县


/// </summary>


Xian,




/**//// <summary>


/// 镇


/// </summary>


Zhen


}



完成
最后是测试页


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;




public partial class _Default : System.Web.UI.Page




...{


protected void Page_Init()




...{


//this.AreaControl1.OnlySFCS = true;


}




protected void Page_Load(object sender, EventArgs e)




...{


//要通过给控件赋值,绑定相应地区,只需给 ID 即可,Name就不用了


//this.AreaControl1.SFID = 42;


//this.AreaControl1.CSID = 4205;


//this.AreaControl1.XianID = 420521;


//this.AreaControl1.ZhenID=35020303;


//this.AreaControl1.OnlySFCS = true;


this.AreaControl1.IsVertical=true;


this.AreaControl1.IsDisplayName = true;


//this.AreaControl1.IsDisabled=true;


}




protected void Button1_Click(object sender, EventArgs e)




...{


//添加一个按钮 用来读取 用户选择的地区信息


Response.Write(String.Format("{0}{4},{1}{5},{2}{6},{3}{7}", AreaControl1.SF, AreaControl1.CS, AreaControl1.Xian, AreaControl1.Zhen, AreaControl1.SFID, AreaControl1.CSID, AreaControl1.XianID, AreaControl1.ZhenID));


}




protected void Button2_Click(object sender, EventArgs e)




...{


//直接调用 AreaControl 里的 SaveCookie 把 用户选择的地区存入 Cookie (这是为了方便,集成的)


this.AreaControl1.SaveCookie();


}


}






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






<%...@ Register Src="AreaControl.ascx" TagName="AreaControl" TagPrefix="uc1" %>








<!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>


</head>


<body>


<form id="form1" runat="server">


<div>


<uc1:AreaControl id="AreaControl1" runat="server"></uc1:AreaControl>


<asp:Button ID="Button1" runat="server" Text="跳转" OnClick="Button1_Click" />


<asp:Button ID="Button2" runat="server" Text="存 Cookie" OnClick="Button2_Click" />




</div>


</form>


</body>


</html>



记得 是 AjaxPro 6.10.4.1 的版本

Web.Config 在<system.web>来上这句


<httpHandlers>


<add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2"/>


</httpHandlers>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: