CasCadingDropDown
最近我需要有多層式(三層式)下拉的功能
本想利用最直接的方法,就是3個DropDownList+Update Panel防止他PostBack
可是利用了之後,我發現這3個DropDownList還是會一閃一閃
雖然此時不會PostBack,可是我看他一閃一閃的,實在很討厭咧=.=
因此這裡我轉向去利用CasCadingDropDown這個Ajax Extender
要利用CasCadingDropDown必須有3個前置作業
第一:使用用Web Service的方式去呼叫
第二:在Web Service的前面要先宣告
<System.Web.Script.Services.ScriptService()> _
第三:如果DropDownList有事件會觸發或是其它控制項的事件會影響DropDownList的話,要在Page的前置詞補上
<%@ Page EnableEventValidation="false" %>
有了上述三個前置作業,接下來就要開始實作,這邊我以VB的方式呈現
並以Northwind資料庫為例,根據Category的選擇,來呈現Product的內容
Step 1:
在畫面上我們拖曳ScriptManager、2個DropDownList(ddlCategory,ddlProduct)及1個CasCadingDropDown控制項,畫面會像如圖
Step 2 :
接著我們去Page_Load事件預先載入Category的項目,完成後的畫面大概是呈現如下
Imports System.Data
Imports System.Data.SqlClient
Partial Class CasCading
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If (Not IsPostBack) Then
BindData()
End If
End Sub
Protected Sub BindData()
Dim connString As String = System.Configuration.ConfigurationManager.AppSettings("Northwind_Connection").ToString()
Dim conn As New SqlConnection(connString)
conn.Open()
Dim sql As String = "SELECT * FROM Categories"
Dim dr As New SqlDataAdapter(sql, conn)
Dim ds As New DataSet
dr.Fill(ds)
ddlCategory.DataSource = ds
ddlCategory.DataTextField = "CategoryName"
ddlCategory.DataValueField = "CategoryID"
ddlCategory.DataBind()
End Sub
End Class
Step 3 :
還記得我們剛才講的,要利用CasCadingDropDown的方式必須透過Webservice的方式
這邊我新增一支Webservce命名為CascadingDropDownlist
接著在最前面宣告
<System.Web.Script.Services.ScriptService()> _
最後我們就可以開始來撰寫我們的CasCadingDropDown的Webservice了
我宣告一個Function GetContents回傳CascadingDropDownNameValue的陣列
CascadingDropDownNameValue的陣列方法是AjaxControlToolkit裡面的
詳細的程式碼,大概會像以下的畫面
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Data
Imports System.Data.SqlClient
' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
' <System.Web.Script.Services.ScriptService()> _
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<System.Web.Script.Services.ScriptService()> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class CascadingDropDownlist
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function HelloWorld() As String
Return "Hello World"
End Function
<WebMethod()> _
Public Function GetContents(ByVal knownCategoryValues As String, ByVal category As String) As AjaxControlToolkit.CascadingDropDownNameValue()
Dim connString = System.Configuration.ConfigurationManager.AppSettings("Northwind_Connection").ToString()
Dim conn As New SqlConnection(connString)
conn.Open()
'knownCategoryValues傳進來會以"undefined:DropdownList.id;"的方式進來
'如我第一個DropDownList的id為1,則他會呈現"undefined:1;"
'因此這邊我要抓出Dropdownlist的值,也就是index為1的
Dim categoryValues() As String = knownCategoryValues.Split(":"c, ";"c)
Dim categoryID As Integer = Convert.ToInt32(categoryValues(1))
Dim ds As New DataSet
Dim sql As String = "SELECT ProductID, ProductName from Products WHERE CategoryID='" + categoryID.ToString() + "'"
Dim dap As New SqlDataAdapter(sql, conn)
dap.Fill(ds)
Dim itemCollection As List(Of AjaxControlToolkit.CascadingDropDownNameValue) = New List(Of AjaxControlToolkit.CascadingDropDownNameValue)
For Each dr As DataRow In ds.Tables(0).Rows
itemCollection.Add(New AjaxControlToolkit.CascadingDropDownNameValue(dr("ProductName"), dr("ProductID")))
Next
Return itemCollection.ToArray()
End Function
End Class
最後我們回到Step 1,要設定的CasCadingDropDown屬性
<cc1:CascadingDropDown ID="CascadingDropDown1" runat="server"
ParentControlID="ddlCategory" TargetControlID="ddlProduct" ServicePath="CascadingDropDownlist.asmx"
PromptText="Select the item" ServiceMethod="GetContents" Category="CategoryName">
</cc1:CascadingDropDown>
其中,ServicePath表示Webservice的所在位置,而ServiceMethod表示我們Webservice的方法
詳細的屬性值,請點選CascadingDropDown
最後再提一下,我們的Webservice回傳是以CascadingDropDownNameValue陣列方式,
然而我們也可以以泛型來回傳,如果各位有興趣的話,可下載附件參考