[問答集] 連動DropDownList With Repeater
這是在論壇裡看到的一則發問,其實原發問者沒有詳細的說明原因,只問了
『dropdownlist要連動也要預選』,不過仔細看了一下發問者貼上來的Code,
發現其DropDownList 其實是包在Repeater裡的,也就是說真正的問題應該
是『在Repeater裡如何達到連動式選單』
這個問題大致有幾個地方要了解一下
(1)首先要知道Repeater這類的元件一定會有個ItemDataBound的部份,雖然名稱
可能不盡相同,不過含義是差不多,也就是把資料項目一筆筆給Render出來,例如:
Repeater 的 ItemDataBound / GridView 的 RowDataBound / DataList 的 ItemDataBound
(2)要如何取得同一筆資料中彼此連動的物件,也就是要知道所謂的FindControl,
在此就不多做解釋,有關FindControl可參考之前小弟的另一篇文章
(3)因為要連動,所以觸發連動的元件一定會有其引發連動的事件,以原發問者的案例會是
DropDownList 的SelectedIndexChanged事件
瞭解這幾個點之後,大致上應該就沒什麼太大的問題,這裡就初步做了個範例
( 此範例沒有考慮太多條件判斷,實際應用時該判斷的部份請自行考慮囉!)
範例:在Repeater裡提供三個DropDownList ,分別進行國家/地區/郵地區號的連動選擇
(1)畫面上我們拉了一個Repeater控制項,並且在ItemTemplate裡設計好所需的版面
及DropDownList控制項
(2)接著撰寫一個獨立的Method進行在Repeater 的資料繫結
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
DataLoad();
}
private void DataLoad()
{
using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
{
conn.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandText = "select top 10 id from basecode";
IDataReader idr = command.ExecuteReader();
this.Repeater1.DataSource = idr;
this.Repeater1.DataBind();
}
conn.Close();
}
}
(3)接著如前面我們所分析的,在Repeater 的 ItemDataBound ,我們要針對DropDownList
控制項進行資料繫結及預設值,並且三個DropDownList 有連動間的關係,在這個部份選擇
撰寫三個獨立的Method來進行
a.國別的DropDownList ,具有二個參數,分別DropDownList 控制項及defvalue
private void BindCountry(DropDownList country,string defvalue)
{
using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
{
conn.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandText = "select id,name from country order by code";
IDataReader idr = command.ExecuteReader();
country.DataSource = idr;
country.DataTextField = "name";
country.DataValueField = "id";
country.DataBind();
}
conn.Close();
}
if (!string.IsNullOrEmpty(defvalue))
country.SelectedValue = defvalue.ToLower();
}
b.地區別的DropDownList ,具有三個參數,分別DropDownList 控制項及國別的Value及defvalue
private void BindCity(DropDownList city,Guid countryval, string defvalue)
{
using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
{
conn.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandText = "select id,name from city where countryid=@countryid order by name";
command.Parameters.Add("@countryid", DbType.Guid).Value = countryval;
IDataReader idr = command.ExecuteReader();
city.DataSource = idr;
city.DataTextField = "name";
city.DataValueField = "id";
city.DataBind();
}
conn.Close();
}
if (!string.IsNullOrEmpty(defvalue))
city.SelectedValue = defvalue.ToLower();
}
c.郵地區號的DropDownList ,具有三個參數,分別DropDownList 控制項及地區別的Value及defvalue
private void BindZip(DropDownList zip, Guid cityval, string defvalue)
{
using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
{
conn.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandText = "select id,name from zip where cityid=@cityid order by code";
command.Parameters.Add("@cityid", DbType.Guid).Value = cityval;
IDataReader idr = command.ExecuteReader();
zip.DataSource = idr;
zip.DataTextField = "name";
zip.DataValueField = "id";
zip.DataBind();
}
conn.Close();
}
if (!string.IsNullOrEmpty(defvalue))
zip.SelectedValue = defvalue.ToLower();
}
d.在Repeater 的 ItemDataBound ,進行DropDownList 各自的DataBind動作及Set defvalue
,這裡的程式碼就比較簡潔了,因為已經把DropDownList 各自的DataBind的部份拉出去額外
撰寫,所在這裡的重點就是要知道如何FindControl,然後進行各自DataBind的呼叫,另外由於
第2,3個DropDownList 需要取得前一個的Value,因此在BindCity & BindZip額外提供了前項
的SelectValue值的參數傳入
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
DropDownList country =(DropDownList) e.Item.FindControl("Country");
DropDownList city = (DropDownList)e.Item.FindControl("City");
DropDownList zip = (DropDownList)e.Item.FindControl("Zip");
BindCountry(country, "3B324BC4-8E29-4158-9A4B-EB3A3038ABDE");
BindCity(city, new Guid(country.SelectedValue), "4C56DE70-03C0-4026-A37C-6970101F2809");
BindZip(zip, new Guid(city.SelectedValue), "20D25662-D508-40C4-BDD4-633750803BEB");
}
(4)此外由於選項間必須要有連動的作業,因此在DropDownList的SelectedIndexChanged裡
,也須進行連動式的資料繫結,這裡的重點也是要知道如何Find到同一筆資料中的要連動的相
關控制項,所以我們利用NamingContainer來Find相關的Control
protected void Country_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList country = ((DropDownList)sender);
DropDownList city = (DropDownList)country.NamingContainer.FindControl("City"); //利用NamingContainer來Find相關的Control
DropDownList zip = (DropDownList)country.NamingContainer.FindControl("zip");//利用NamingContainer來Find相關的Control
BindCity(city, new Guid(country.SelectedValue),"");
BindZip(zip, new Guid(city.SelectedValue), "");
}
protected void City_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList city = ((DropDownList)sender);
DropDownList zip = (DropDownList)city.NamingContainer.FindControl("zip");//利用NamingContainer來Find相關的Control
BindZip(zip, new Guid(city.SelectedValue), "");
}
(5)結果
以上就是這個簡單範例的程式碼,當然這只是其中一種做法,此外這個範例中並未做太多的條件
判斷或是效能等等的考量,實務運用上還是要多加一些嚴謹的判斷及控制
重點還在於當理解原理之後,不管是用Repeater 或是GridView或是DataList,應該都是可以迎刃而解囉
By No.18