[编]使用CascadingDropDown实现级联式下拉框

简介: 使用CascadingDropDown实现级联式下拉框 引言 级联式下拉框,有时也叫联动下拉框,也是Web页面中一个很常见的功能。就是假设有若干个下拉框,比如说有3个,分别显示 省份、城市、街道,当选择某一省份后,城市下拉框仅显示属于该省的城市,选择好城市之后,街道下拉框仅显示属于该城市的街道。

使用CascadingDropDown实现级联式下拉框

引言

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

数据库和数据访问

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

  1. 新建一个解决方案,添加网站,并且在App_Data中创建一个数据库SiteDB。
  2. 在SiteDB中创建三张表,分别为Province(Id, Name),City(Id, Name, ProvinceId),Street(Id, Name, CityId)。其中Id为int自增类型,且为主键;Name为Varchar(50)。ProvinceId和CityId则为外键。
  3. 为上面三个表添加一些范例数据,如果你觉得麻烦,那么可以拷贝本文附带代码中的数据库。
  4. 在App_Code中添加一个SiteDataSet数据集。然后打开“Server Explore(服务器浏览器)”将上面三张表拖进去。
  5. 分别对它们的TableAdapter进行配置,其中Province的为获得全部数据,而City和Street分别根据ProvinceId和CityId获取数据,最终的SiteDataSet如下图所示:

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

Web页面布局和设置

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

<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Services>
        <asp:ServiceReference Path="~/AddressService.svc" />
    </Services>
</asp:ScriptManager>

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

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

<ajaxControlToolkit:CascadingDropDown ID="CascadingDropDown1"
        runat="server"
        TargetControlID="ddlProvince"
        Category="Province"
        PromptText="请选择省份...."
        LoadingText="加载中,请稍后 ..."
        ServicePath="AddressService.svc"
        ServiceMethod="GetProvince"
        >
</ajaxControlToolkit:CascadingDropDown>
<ajaxControlToolkit:CascadingDropDown ID="CascadingDropDown2"
        runat="server"                 
        TargetControlID="ddlCity"
        ParentControlID="ddlProvince"
        Category="City"
        PromptText="请选择城市...."
        LoadingText="加载中,请稍后 ..."
        ServicePath="AddressService.svc"
        ServiceMethod="GetCity"
        >
</ajaxControlToolkit:CascadingDropDown>    
<ajaxControlToolkit:CascadingDropDown ID="CascadingDropDown3"
        runat="server"                 
        TargetControlID="ddlStreet"
        ParentControlID="ddlCity"
        Category="Street"
        PromptText="请选择城市...."
        LoadingText="加载中,请稍后 ..."
        ServicePath="AddressService.svc"
        ServiceMethod="GetStreet"
        >
</ajaxControlToolkit:CascadingDropDown>

这三个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中对它进行注册:

<compilation debug="true">
    <assemblies>
        <add assembly="AjaxControlToolkit, Version=3.0.20820.37372, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"/>
        <!-- 省略其他 -->
    </assemblies>
</compilation>

接下来我们来实现这三个方法,先看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<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();

        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<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();

    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<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();

    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获得其下所包含的城市,这些代码大家应该已经很熟悉了。

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

总结

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

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

目录
相关文章
|
5月前
layUI数据表格可编辑扩展下拉框
layUI数据表格可编辑扩展下拉框
|
3月前
|
Web App开发 小程序 Android开发
Uniapp from 表单组件 多层选择 开关 评分 滑块 步进器 日期框 级联选择 下拉列表 复选框 单选框 多行文本 单行文本 textarea radio checkbox picker
Uniapp from 表单组件 多层选择 开关 评分 滑块 步进器 日期框 级联选择 下拉列表 复选框 单选框 多行文本 单行文本 textarea radio checkbox picker
34 0
|
9月前
|
存储 C语言
ArcGIS:Excel/Txt 文件生成点图层、属性表编辑的基本方法、属性表之间的连接(合并)和关联的操作、属性表的字段计算器的使用
ArcGIS:Excel/Txt 文件生成点图层、属性表编辑的基本方法、属性表之间的连接(合并)和关联的操作、属性表的字段计算器的使用
188 0
|
5月前
在TableViewer中如何给表格的单元格增加其他组件的编辑功能
在TableViewer中如何给表格的单元格增加其他组件的编辑功能
26 0
|
5月前
|
JavaScript
layUI数据表格可编辑扩展日期框
layUI数据表格可编辑扩展日期框
|
6月前
|
XML 数据格式
FastReport自动提取表的逻辑
FastReport自动提取表的逻辑
|
9月前
|
数据库
机房收费系统——学生基本信息维护(组合查询,选中整行)
机房收费系统——学生基本信息维护(组合查询,选中整行)
40 0
机房收费系统——学生基本信息维护(组合查询,选中整行)
|
JavaScript 数据安全/隐私保护
基于Vue实现跨表格(单选、多选表格项,单表格限制)相互拖拽
基于Vue实现跨表格(单选、多选表格项,单表格限制)相互拖拽
PowerDesigner16:显示工具栏、物理模型绘制表之间关系、设计图导出成图片
PowerDesigner16:显示工具栏、物理模型绘制表之间关系、设计图导出成图片
412 0
PowerDesigner16:显示工具栏、物理模型绘制表之间关系、设计图导出成图片
|
Web App开发 SQL JavaScript
【自然框架】分享 n级联动下拉列表框
  特点:1、 使用js方法,把需要的数据一次性写入到页面里,然后用js来实现联动的效果。2、 支持n级。3、 封装成了服务器控件,所以使用非常简单。4、 支持在回发的时候保持状态。5、 支持修改记录的时候设置默认选项。
1226 0