cascading mysql 主键_[编]使用CascadingDropDown实现级联式下拉框

使用CascadingDropDown实现级联式下拉框

引言

级联式下拉框,有时也叫联动下拉框,也是Web页面中一个很常见的功能。就是假设有若干个下拉框,比如说有3个,分别显示 省份、城市、街道,当选择某一省份后,城市下拉框仅显示属于该省的城市,选择好城市之后,街道下拉框仅显示属于该城市的街道。记得以前做Asp的时候,做一个类似这样的下拉框需要花费不少的力气,编写不少的javascript代码。如今到了Asp.Net时代,使用Ajax Control Toolkit中的CascadingDropDown控件,再配合普通的DropDownList控件以及Web Serive,实现这样一个功能变得非常容易了。本文将一步步来实现它。

数据库和数据访问

这一部分和我们本文要讨论的主题实际上没有关系,但是我们需要“可以级联显示”的数据,因此需要创建一个范例数据库,同时还需要有对它的数据访问方法。对于这部分,我仅给出简单的步骤,依然以省份、城市、街道为例:

新建一个解决方案,添加网站,并且在App_Data中创建一个数据库SiteDB。

在SiteDB中创建三张表,分别为Province(Id, Name),City(Id, Name, ProvinceId),Street(Id, Name, CityId)。其中Id为int自增类型,且为主键;Name为Varchar(50)。ProvinceId和CityId则为外键。

为上面三个表添加一些范例数据,如果你觉得麻烦,那么可以拷贝本文附带代码中的数据库。

在App_Code中添加一个SiteDataSet数据集。然后打开“Server Explore(服务器浏览器)”将上面三张表拖进去。

分别对它们的TableAdapter进行配置,其中Province的为获得全部数据,而City和Street分别根据ProvinceId和CityId获取数据,最终的SiteDataSet如下图所示:

bb107cea71fc6d9fb7e2c88fdf0781ff.gif

OK,这样数据库和数据访问就完毕了,接下来我们看下Web页面。

Web页面布局和设置

首先我们在站点中添加一个“Ajax-enabled WCF Service(启用了AJAX的WCF服务)”,命名为AddressService,暂时不用管它的实现。在ScriptManager中对它进行注册(在本文中这里不注册也可以):

打开Default.aspx,像下图这样对页面进行布局:

ed5803da6c0fea4330a541c28862cc55.gif

三个DropDownList分别的Id为ddlProvince、ddlCity、ddlStreet。之后从AjaxControlToolkit中拖三个CascadingDropDown到页面上,像下面这样对其进行配置:

runat="server"

TargetControlID="ddlProvince"

Category="Province"

PromptText="请选择省份...."

LoadingText="加载中,请稍后 ..."

ServicePath="AddressService.svc"

ServiceMethod="GetProvince"

>

runat="server"

TargetControlID="ddlCity"

ParentControlID="ddlProvince"

Category="City"

PromptText="请选择城市...."

LoadingText="加载中,请稍后 ..."

ServicePath="AddressService.svc"

ServiceMethod="GetCity"

>

runat="server"

TargetControlID="ddlStreet"

ParentControlID="ddlCity"

Category="Street"

PromptText="请选择城市...."

LoadingText="加载中,请稍后 ..."

ServicePath="AddressService.svc"

ServiceMethod="GetStreet"

>

这三个CascadingDropDown分别对应之前添加的通常的DropDownList控件,下面是对其各个属性的一个简单说明:

TargetControlID:与之协作的DropDownList控件的ID。

ParentControlID:父级下拉框的ID,显然顶级下拉框ddlProvince不含有父级下拉框,因此不含有ParentControlID。

Category:此下拉框的“类别”,也可以称为名称,具体使用到后面再说,这里说了也不好理解。

PromptText:进行选择之前显示的文本。

LoadingText:加载时显示的文本,因为需要与服务端进行通信,所以难免会产生延迟,这里的文本便是在延迟时显示的文本。

ServicePath:获取数据时的Web服务。此处即为我们的WCF服务。

ServiceMethod:获取数据的方法。这些方法由WCF服务实现,显然我们暂时并没有实现它。

好了,现在页面部分就设置完毕了,我们最后看下WCF服务的实现,它仅仅是使用第一步创建的数据集来获取数据。

编写WCF服务代码

WCF服务所要实现的实际就是上面CascadingDropDown中所设置的三个用于获取数据的方法:GetProvince()、GetCity()和GetStreet()。因为需要在页面的后置代码中使用AjaxControlToolkit所定义的类型,所以如果你和我一样使用了GAC来部署AjaxControlToolkit程序集的话,那么需要首先在Web.Config中对它进行注册:

接下来我们来实现这三个方法,先看App_Code中AddressService下的GetProvince()方法的实现,显然,它获得所有的省份:

public class AddressService

{

[OperationContract]

public CascadingDropDownNameValue[] GetProvince(string knownCategoryValues, string category)

{

Thread.Sleep(1000); // 等待1秒,模拟网络延迟

SiteDataSetTableAdapters.ProvinceTableAdapter provinceAdapter

= new SiteDataSetTableAdapters.ProvinceTableAdapter();

SiteDataSet.ProvinceDataTable provinceTable = provinceAdapter.GetProvince();

List values = new List();

foreach (SiteDataSet.ProvinceRow province in provinceTable) {

string id = province.Id.ToString();

string name = province.Name;

values.Add(new CascadingDropDownNameValue(name, id));

}

return values.ToArray();

}

}

我们先看下方法的签名,第2个参数category即是我们在CascadingDropDown中定义的category属性的值,它传到了这里供我们做一些处理。第1个参数以“Category:Id”的形式包含父下拉框的category值和id值,因为省份为顶级下拉框,所以此时knownCategoryValues为空字符串。返回值为一个CascadingDropDownNameValue数组,其实就是一个键/值对,用于返回给客户端进行绑定。

方法的内容我觉得不需要有任何解释,都是最平常不过的强类型DataSet的基本操作。需要注意的是Thread.Sleep(1000),这里是为了模拟网络延迟的效果,以让控件能够显示出LoadingText的效果。

接下来,我们再看剩下两个方法GetCity和GetStreet方法的实现:

[OperationContract]

public CascadingDropDownNameValue[] GetCity(string knownCategoryValues, string category)

{

Thread.Sleep(1000);

StringDictionary keyValue =

CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

int provinceId = Convert.ToInt32(keyValue["Province"]);

SiteDataSetTableAdapters.CityTableAdapter cityAdapter =

new SiteDataSetTableAdapters.CityTableAdapter();

SiteDataSet.CityDataTable cityTable = cityAdapter.GetCityByProvinceId(provinceId);

List values = new List();

foreach (SiteDataSet.CityRow city in cityTable) {

string id = city.Id.ToString();

string name = city.Name;

values.Add(new CascadingDropDownNameValue(name, id));

}

return values.ToArray();

}

[OperationContract]

public CascadingDropDownNameValue[] GetStreet(string knownCategoryValues, string category) {

Thread.Sleep(1000);

StringDictionary keyValue =

CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);

int cityId = Convert.ToInt32(keyValue["City"]);

SiteDataSetTableAdapters.StreetTableAdapter streetAdapter =

new SiteDataSetTableAdapters.StreetTableAdapter();

SiteDataSet.StreetDataTable streetTable = streetAdapter.GetStreetByCityId(cityId);

List values = new List();

foreach (SiteDataSet.StreetRow street in streetTable) {

string id = street.Id.ToString();

string name = street.Name;

values.Add(new CascadingDropDownNameValue(name, id));

}

return values.ToArray();

}

这两个方法是完全类似的,所以我们仅就GetCity()方法说明。假如我们此刻在页面选择了省份,为“陕西”,且它的id为“2”,那么按照上面的说明,knownCategoryValues包含的值为“Province:2”,它含有了父控件的category值和选中的id值,通过它我们就可以获得选中的省份id。我们并不需要手动去处理这个字符串,比如使用Split()方法,而可以使用CascadingDropDown.ParseKnownCategoryValuesString静态方法来完成,如上面的代码所示。

在获得了省份id之后,我们可以调用DataAdapter上的方法,来根据省份id获得其下所包含的城市,这些代码大家应该已经很熟悉了。

好了,现在一切已经就绪,大家可以打开页面看一下实际的效果了:

b7544c3b36c7e685ca8666b6258e8867.gif

总结

在这篇文章中,我们又实现了Web中的一个常见功能:级联式下拉框。我们先创建了范例数据库,以及一个强类型DataSet用作数据访问。随后对Web页面进行了布局,设置了控件属性。最后编写了WCF服务,获取客户端所需要的数据。

感谢阅读,希望这篇文章能给你带来帮助!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现级联下拉菜单的一般步骤如下: 1. 创建一个HTML表单,并在表单中定义两个或多个select元素。 2. 为每个select元素定义一个id属性,以便在JavaScript代码中引用它们。 3. 在JavaScript中,使用XMLHttpRequest对象创建一个AJAX请求。 4. 通过AJAX请求从服务器端获取数据。 5. 将获取到的数据解析为JSON格。 6. 为第一个select元素添加一个onchange事件处理程序,当用户选择一个选项时,触发该事件处理程序。 7. 在事件处理程序中,使用已选择的选项值作为参数,向服务器端发送AJAX请求。 8. 在服务器端,检索并返回与第一个选项相关的数据。 9. 将返回的数据解析为JSON格。 10. 使用解析后的数据更新第二个select元素的选项列表。 下面是一个简单的实现级联下拉菜单的示例代码: ```html <!DOCTYPE html> <html> <head> <title>Cascading Dropdowns</title> <script type="text/javascript"> function getData(selectId, parentId) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { var response = JSON.parse(xhr.responseText); var select = document.getElementById(selectId); select.options.length = 0; for (var i = 0; i < response.length; i++) { var option = document.createElement("option"); option.value = response[i].id; option.text = response[i].name; select.add(option); } } }; xhr.open("GET", "get_data.php?parent_id=" + parentId, true); xhr.send(); } </script> </head> <body> <form> <label for="category">Category:</label> <select id="category" onchange="getData('subcategory', this.value);"> <option value="">Select a category</option> <option value="1">Books</option> <option value="2">Electronics</option> <option value="3">Clothing</option> </select> <br> <label for="subcategory">Subcategory:</label> <select id="subcategory"> <option value="">Select a subcategory</option> </select> </form> </body> </html> ``` 在这个示例中,我们创建了一个包含两个select元素的表单。第一个select元素用于选择主分类,第二个select元素用于选择子分类。当用户选择一个主分类时,我们使用getData函数向服务器发送一个AJAX请求,并传递所选分类的ID作为参数。服务器返回与所选分类相关的子分类数据,并将其解析为JSON格。我们使用JavaScript代码动态更新第二个select元素的选项列表,以显示与所选主分类相关的子分类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值