抽点时间写了一个自定义空间,功能是这样的,实现省份,城市的级联更新.数据源是数据库,设计思路是这样的,利用prototype1.5 提供的AJAX功能实现控件级联无刷新功能,请求一个Httphandler,读取数据.
控件呈现:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ucar.Common;
using System.Data;
using Ucar.Components.Caching;
namespace BitAuto.Ucar.CarSelectSortData
... {
[DefaultProperty("Text")]
[ToolboxData("<{0}:CitySelect runat=server></{0}:CitySelect>")]
public class CitySelect : WebControl, INamingContainer, IPostBackDataHandler
...{
private string _validationExpression = @"^[1-9]d*$";
/// <summary>
/// 控件集合
/// </summary>
private Label lblProvince = new Label();
private DropDownList dropProvince = new DropDownList();
private Label lblCity = new Label();
private DropDownList dropCity = new DropDownList();
private RegularExpressionValidator valeCityValue = new RegularExpressionValidator();
//控件属性#region //控件属性
/// <summary>
/// 城市ID
/// </summary>
[Bindable(true)]
[Category("Value")]
[DefaultValue("0")]
[Localizable(true)]
[Description("Value")]
public string Value
...{
get
...{
if (this.CityId == 0 || this.CityId == -1)
...{
return string.Empty;
}
return ConvertHelper.GetString(this.CityId);
}
set
...{
ViewState["Value"] = value;
}
}
/// <summary>
/// 省份ID
/// </summary>
[Bindable(true)]
[Category("省份ID")]
[DefaultValue("0")]
[Localizable(true)]
[Description("省份ID")]
public int ProvinceId
...{
get
...{
return ConvertHelper.GetInteger(ViewState["ProvinceId"]);
}
set
...{
ViewState["ProvinceId"] = value;
}
}
/// <summary>
/// 城市ID
/// </summary>
[Bindable(true)]
[Category("城市ID")]
[DefaultValue("0")]
[Localizable(true)]
[Description("城市ID")]
public int CityId
...{
get
...{
return ConvertHelper.GetInteger(ViewState["CityId"]);
}
set
...{
ViewState["CityId"] = value;
}
}
/// <summary>
/// 布局方式
/// </summary>
[Bindable(true)]
[Category("布局方式")]
[DefaultValue("Horizontal")]
[Localizable(true)]
[Description("布局方式")]
public RepeatDriections RepeatDriection
...{
get
...{
if (ViewState["RepeatDriection"] == null)
...{
return RepeatDriections.Horizontal;
}
return (RepeatDriections)ViewState["RepeatDriection"];
}
set
...{
ViewState["RepeatDriection"] = value;
}
}
/// <summary>
/// 省份样式
/// </summary>
[Bindable(true)]
[Category("省份样式")]
[DefaultValue("")]
[Localizable(true)]
[Description("省份样式")]
public string ProvinceCssClass
...{
get
...{
return ConvertHelper.GetString(ViewState["ProvinceCssClass"]);
}
set
...{
ViewState["ProvinceCssClass"] = value;
}
}
/// <summary>
/// 城市样式
/// </summary>
[Bindable(true)]
[Category("城市样式")]
[DefaultValue("")]
[Localizable(true)]
[Description("城市样式")]
public string CityCssClass
...{
get
...{
return ConvertHelper.GetString(ViewState["CityCssClass"]);
}
set
...{
ViewState["CityCssClass"] = value;
}
}
/// <summary>
/// 标签是否可见
/// </summary>
[Bindable(true)]
[Category("标签是否可见")]
[DefaultValue("True")]
[Localizable(true)]
[Description("标签是否可见")]
public bool LableVisible
...{
get
...{
if (ViewState["LableVisible"] == null)
...{
return true;
}
return ConvertHelper.GetBoolean(ViewState["LableVisible"]);
}
set
...{
ViewState["LableVisible"] = value;
}
}
[Category("是否启用非空验证")]
[DefaultValue(false)]
[Description("是否启用非空验证")]
public bool EnabledRequiredFieldValidator
...{
get
...{
return ConvertHelper.GetBoolean(ViewState["EnabledRequiredFieldValidator"]);
}
set
...{
ViewState["EnabledRequiredFieldValidator"] = value;
}
}
[Category("验证提示信息")]
[DefaultValue("请选择城市!")]
[Description("验证提示信息")]
public string ErrorMessage
...{
get
...{
return ConvertHelper.GetString(ViewState["ErrorMessage"]);
}
set
...{
ViewState["ErrorMessage"] = value;
}
}
[Category("验证分组")]
[DefaultValue("")]
[Description("验证分组")]
public string ValidationGroup
...{
get
...{
return ConvertHelper.GetString(ViewState["ValidationGroup"]);
}
set
...{
ViewState["ValidationGroup"] = value;
}
}
#endregion
protected override void RenderContents(HtmlTextWriter output)
...{
if (this.Page != null)
...{
this.Page.VerifyRenderingInServerForm(this);
}
output.AddAttribute(HtmlTextWriterAttribute.Type, "hidden");
output.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID + "_hdProvinceId");
output.AddAttribute(HtmlTextWriterAttribute.Id, this.UniqueID + "_hdProvinceId");
output.AddAttribute(HtmlTextWriterAttribute.Value, this.ProvinceId.ToString());
output.RenderBeginTag(HtmlTextWriterTag.Input);
output.RenderEndTag();
output.AddAttribute(HtmlTextWriterAttribute.Type, "hidden");
output.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
output.AddAttribute(HtmlTextWriterAttribute.Id, this.UniqueID + "_hdCityId");
output.AddAttribute(HtmlTextWriterAttribute.Value, this.CityId.ToString());
output.RenderBeginTag(HtmlTextWriterTag.Input);
output.RenderEndTag();
if (RepeatDriection == RepeatDriections.Vertical)
...{
output.RenderBeginTag(HtmlTextWriterTag.Div);
output.Write("<DIV class='" + this.ProvinceCssClass + "' >");
lblProvince.RenderControl(output);
output.Write(" ");
dropProvince.RenderControl(output);
output.Write("</DIV>");
output.Write("<DIV class='" + this.CityCssClass + "' >");
lblCity.RenderControl(output);
output.Write(" ");
dropCity.RenderControl(output);
output.Write("</DIV>");
}
else
...{
output.RenderBeginTag(HtmlTextWriterTag.Div);
lblProvince.RenderControl(output);
output.Write(" ");
dropProvince.RenderControl(output);
output.Write(" ");
lblCity.RenderControl(output);
output.Write(" ");
dropCity.RenderControl(output);
}
valeCityValue.RenderControl(output);
}
protected override void CreateChildControls()
...{
//省份标签
lblProvince.Text = "省份";
lblProvince.ID = "lblCarProducer";
lblProvince.Visible = LableVisible;
this.Controls.Add(lblProvince);
dropProvince.ID = "dropProvince";
this.Controls.Add(dropProvince);
//城市
lblCity.Text = "城市";
lblCity.ID = "lblCarBrand";
lblCity.Visible = LableVisible;
this.Controls.Add(lblCity);
dropCity.ID = "dropCity";
this.Controls.Add(dropCity);
valeCityValue.ID = "_valeCityValue";
valeCityValue.ControlToValidate = this.dropCity.ID;
valeCityValue.Display = ValidatorDisplay.None;
valeCityValue.ErrorMessage = this.ErrorMessage;
valeCityValue.ValidationExpression = _validationExpression;
valeCityValue.ValidationGroup = this.ValidationGroup;
valeCityValue.SetFocusOnError = true;
valeCityValue.Enabled = this.EnabledRequiredFieldValidator;
this.Controls.Add(valeCityValue);
dropProvince.Attributes.Add("onchange", "cityLoad(" + this.dropProvince.ClientID + "," + this.dropCity.ClientID + "," + this.UniqueID + "_hdProvinceId" + "," + this.UniqueID + "_hdCityId" + ");");
dropCity.Attributes.Add("onchange", "SetCityID(" + this.UniqueID + "_hdCityId" + "," + this.dropCity.ClientID + ");");
}
protected override void OnInit(EventArgs e)
...{
Page.RegisterRequiresControlState(this);
Page.ClientScript.RegisterClientScriptResource(typeof(CitySelect), "BitAuto.Ucar.CarSelectSortData.prototype1.5.1.js");
Page.ClientScript.RegisterClientScriptResource(typeof(CitySelect), "BitAuto.Ucar.CarSelectSortData.CityChange.js");
base.OnInit(e);
}
protected override void OnPreRender(EventArgs e)
...{
InitProvince();
if (this.CityId != 0)
...{
this.ProvinceId = City.GetProvinceIdByCityId(this.CityId);
}
if (this.ProvinceId != 0)
...{
dropProvince.SelectedValue = ProvinceId.ToString();
}
InitCity();
if (CityId != 0)
...{
ControlHelper.InitDropDownListByValue(dropCity, CityId.ToString());
//dropCity.SelectedValue = CityId.ToString();
//dropCity.SelectedIndex = dropCity.Items.IndexOf(dropCity.Items.FindByValue(CityId.ToString()));
}
base.OnPreRender(e);
}
IPostBackDataHandler 成员#region IPostBackDataHandler 成员
public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
...{
string presentValue = this.ProvinceId.ToString();
string postedValue = postCollection[this.UniqueID];
string postedProvinceValue = postCollection[this.UniqueID + "_hdProvinceId"];
if (presentValue == null || !presentValue.Equals(postedValue))
...{
this.CityId = ConvertHelper.GetInteger(postedValue);
this.ProvinceId = ConvertHelper.GetInteger(postedProvinceValue);
return true;
}
return false;
}
public void RaisePostDataChangedEvent()
...{
}
#endregion
//绑定方法#region //绑定方法
protected void InitProvince()
...{
dropProvince.Items.Clear();
DataView dv = City.GetProvinceCache();
dv.RowFilter = "pvc_Id<>0";
dropProvince.DataTextField = "pvc_Name";
dropProvince.DataValueField = "pvc_Id";
dropProvince.DataSource = dv;
dropProvince.DataBind();
dropProvince.Items.Insert(0, new ListItem("请选择省份", ""));
}
protected void InitCity()
...{
dropCity.Items.Clear();
DataView dvCity = City.GetCityCache();
if (this.ProvinceId != 0)
...{
dvCity.RowFilter = "pvc_Id=" + dropProvince.SelectedValue;
dropCity.DataTextField = "city_Name";
dropCity.DataValueField = "city_Id";
dropCity.DataSource = dvCity;
dropCity.DataBind();
}
dropCity.Items.Insert(0, new ListItem("请选择城市", "0"));
}
#endregion
/// <summary>
/// 布局方式
/// </summary>
public enum RepeatDriections
...{
Vertical,//垂直
Horizontal//水平
}
}
}
Handler实现:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Web;
using Ucar.Common;
using Ucar.Components.Caching;
namespace BitAuto.Ucar.CarSelectSortData
... {
public class CityHandler : IHttpHandler
...{
IHttpHandler 成员#region IHttpHandler 成员
public bool IsReusable
...{
get ...{ throw new Exception("The method or operation is not implemented."); }
}
public void ProcessRequest(HttpContext context)
...{
OutputCity(context);
}
#endregion
/// <summary>
/// 输出
/// </summary>
protected void OutputCity(HttpContext context)
...{
string ProvinceIdStr = context.Request["ProvinceId"];
if (!string.IsNullOrEmpty(ProvinceIdStr))
...{
DataView dvCity = City.GetCityCacheByProvinceId(ProvinceIdStr);
StringBuilder sb = new StringBuilder();
int i = 0;
for (i = 0; i < dvCity.Table.Rows.Count; i++)
...{
sb.Append(dvCity.Table.Rows[i]["city_Name"] + "," + dvCity.Table.Rows[i]["city_Id"] + ",");
}
context.Response.Write(sb.ToString().TrimEnd(','));
}
}
}
}
JS:
function cityLoad(dropProvinceid,dropCityid,hdProvinceId,hdCityId)
... {
var father= $F(dropProvinceid);
$(hdProvinceId).value=father;
$(hdCityId).value = '';
if(father!=0)
...{
var url = "~/AjaxCity.aspx";
var pars = "provinceID=" + father;
var myAjax = new Ajax.Request(url,...{method: 'get', parameters: pars, onComplete:function(originalRequest)...{showResponse(originalRequest,dropCityid)}});
}
else
...{
var sel = $(dropCityid);
sel.update("");
CreatOptions(sel,"请选择城市","");
}
}
function SetCityID(hdCityId,dropCity)
... {
$(hdCityId).value=$F(dropCity);
}
function showResponse(result,dropCityid)
... {
var sel = $(dropCityid);
var val = result.responseText.split(',');
sel.update("");
CreatOptions(sel,"请选择城市","");
for(i=0;i<val.length;i++)
...{
text = val[i];
value = val[++i];
CreatOptions(sel,text,value);
}
}
function CreatOptions(colls,text,value)
... {
colls.options.add(new Option(text,value));
}
在使用的时候配下hander和连接字符串.
< httpHandlers >
< remove verb ="*" path ="*.asmx" />
< add verb ="*" path ="AjaxCity.aspx" validate ="false" type ="BitAuto.Ucar.CarSelectSortData.CityHandler,BitAuto.Ucar.CarSelectSortData" />
</ httpHandlers >