Asp.net MVC中的DropDownLists貌似會讓一開始從Asp.net Forms轉過來的程式員造成不少迷惑.這篇文章講述了為了使用DropDownLists,你需要在Asp.Net MVC中知道的方方面面.
DropDownList,ComboBox,無論你喜歡怎麼稱呼這些,他們毫無例外的會被產生為html select標籤.在<select>開標籤和</select>閉標籤之間,每一個列表元素都必須被包裹於<option>標籤.當然你也可以使用<optgroup>標籤將各個選項按邏輯上分成不同的組。如果針對<option>設定了value屬性,則Value屬性就是在form提交時select元素的值.而如果忘了給value屬性賦值,則在<option></option>標籤內包裹的內容則是被提交的值。
為了簡便起見,這裡我先用一個靜態列表作為例子,你可以將這些作為html直接加入到你的View中:
<select name="year"> <option>2010</option> <option>2011</option> <option>2012</option> <option>2013</option> <option>2014</option> <option>2015</option></select>
或者,給列表加點小動態,假如需要列表的年份會隨著新年到來之際自動往後推1年:
<select name="year"> <option><%= DateTime.Now.Year %></option> <option><%= DateTime.Now.AddYears(1).Year %></option> <option><%= DateTime.Now.AddYears(2).Year %></option> <option><%= DateTime.Now.AddYears(3).Year %></option> <option><%= DateTime.Now.AddYears(4).Year %></option> <option><%= DateTime.Now.AddYears(5).Year %></option></select>
甚至可以更簡便:
<select name="year"> <% for (var i = 0; i < 6; i++){%> <option><%= DateTime.Now.AddYears(i).Year %></option> <%}%></select>
上面三個程式碼片段產生效果相同,如下:
如果的資料是來自資料庫,那最好還是使用Html.DropDownList()擴充方法的八個重載方法來建立DropDownList.在這裡我並不會一一說明這些不同的重載,但是會說明主要重載。第一種重載-public static string DropDownList(this HtmlHelper htmlHelper, string name) -僅僅接受一個string類型的參數.協助文檔中只是簡單說明了這個string參數是<select>的name屬性是遠遠不夠的,這個參數不僅是<select>元素的name和id的值,還用於在ViewData尋找元素,如果這個string參數和ViewData的key相匹配,ViewData元素會和helper進行綁定來建立<option>,同時,ViewData元素的類型必須是SelectListItems的集合.下面代碼是使用LINQ TO SQL來從Northwind資料庫中提取種類,使用DropDownList擴充方法的第一個重載:
public ActionResult Index(){ var db = new NorthwindDataContext(); IEnumerable<SelectListItem> items = db.Categories .Select(c => new SelectListItem { Value = c.CategoryID.ToString(), Text = c.CategoryName }); ViewData["CategoryID"] = items; return View();}
注意每一個SelectListItem對象都必須給Value和Text屬性進行賦值。他們會在運行時分別匹配到html的<option>的value屬性和<option></option>之間的內容。注意這裡ViewData的key用“CategoryID”顯得有點奇怪,但實際上CategoryID正式<select>向伺服器提交的值,所以使用這樣的命名是有實際意義的。在View中,使用重載方法:
<%= Html.DropDownList("CategoryID") %>
而對應產生的HTML如下:
<select id="CategoryID" name="CategoryID"> <option value="1">Beverages</option> <option value="2">Condiments</option> <option value="3">Confections</option> <option value="4">Dairy Products</option> <option value="5">Grains/Cereals</option> <option value="6">Meat/Poultry</option> <option value="7">Produce</option> <option value="8">Seafood</option></select>
Html.DropDownList的第二種重載方法-public static string DropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList)-是經常被使用的。在這個重載中,你可以使用IEnumerable<SelectListItem>或者SelectList對象作為參數。首先再看返回上述兩個對象的方法之前,先看在View中的代碼:
<%= Html.DropDownList("CategoryID", (IEnumerable<SelectListItem>) ViewData["Categories"]) %>
我們先說存入ViewData的第一種物件類型-IEnumerable<SelectListItem>對象,代碼和前面的例子很像:
public ActionResult Index(){ var db = new NorthwindDataContext(); IEnumerable<SelectListItem> items = db.Categories .Select(c => new SelectListItem { Value = c.CategoryID.ToString(), Text = c.CategoryName }); ViewData["Categories"] = items; return View();}
再看在ViewData中存入SelectList類型的代碼:
public ActionResult Index(){ var db = new NorthwindDataContext(); var query = db.Categories.Select(c => new { c.CategoryID, c.CategoryName }); ViewData["Categories"] = new SelectList(query.AsEnumerable(), "CategoryID", "CategoryName"); return View();}
使用SelectList使Controller中的代碼稍微整潔了一些,當然在View中也同樣。SelectList的建構函式有好幾個重載可以接受對象作為參數來代表被選擇的選項:
public ActionResult Index(){ var db = new NorthwindDataContext(); var query = db.Categories.Select(c => new { c.CategoryID, c.CategoryName }); ViewData["Categories"] = new SelectList(query.AsEnumerable(), "CategoryID", "CategoryName", 3); return View();}
上面代碼會讓”Confections”在列表產生後被選中:
預設值
上面所有例子都會在頁面載入後預設選擇第一個選項,但很多情況下,需要一個預設值來代替第一個值被選擇,這個預設值可以是空或者是提示使用者”請選擇”,或者類似的。DropDownList還有一個重載可以實現這點-public static string DropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, string optionLabel).
<%= Html.DropDownList("CategoryID", (SelectList) ViewData["Categories"], "--Select One--") %>
CSS和HTML 屬性
DropDownList有四個重載可以在DropDownList被產生後添加HTML 屬性.其中有兩個接受IDictionary<string, object>作為參數,而另外兩個以匿名對象作為參數。下面兩段代碼產生相同的html,都添加CSS選擇符和綁定用戶端onchange()事件:
<%= Html.DropDownList( "CategoryID", (SelectList)ViewData["Categories"], "--Select One--", new Dictionary<string, object> { {"class", "myCssClass"}, {"onchange", "someFunction();"} }) %>
<%=Html.DropDownList( "CategoryID", (SelectList) ViewData["Categories"], "--Select One--", new{ @class = "myCssClass", onchange = "someFunction();" }) %>
你也許已經注意到了第二段代碼中有個叫@class的屬性,它還是會被產生為”class”但class是C#的關鍵字所以需要在屬性名稱前加上”@”,你也許還會想為什麼需要兩個不同的重載來實現為html添加標籤?第二段代碼中使用匿名方法顯得代碼更簡潔和優美,當然選擇第二段的寫法。但是HTML 5的說明中提到可以動態為html元素添加自訂屬性,而自訂屬性必須以“data-”作為開頭,而如果你嘗試在C#對象中建立的屬性名稱中有連字號(譯者注:也就是”-”),就會產程編譯錯誤,所以Dictionary<string, object>作為參數就能很好的解決這個問題。
AutoPostBack哪去了?
從前使用web Form開發的程式員經常會問到AutoPostBack跑哪去了?使用IDE,並且在AutoPostBack打個勾是非常容易的。而正是因為容易使用,所以大多開發人員不會去想AutoPostBack是怎樣的機制。實際上,如果你選擇AutoPostBack,則DropDownList會被添加一個引發javascript事件的onchange屬性,導致DropDownList所在的form被提交。這個過程在MVC中必須手動實現,但是也非常簡單,我下面的代碼用兩種方式實現這點,第一段代碼中的方式通過object作為參數來設定html的屬性,另一段代碼使用jQuery來實現同樣的效果。毫不謙虛的說,我已經將DropDownList在form中的大部使用都寫出來了,下面是第一種方法:
<% using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "TheForm" })){%> <%= Html.DropDownList( "CategoryID", (SelectList) ViewData["Categories"], "--Select One--", new{ onchange = "document.getElementById('TheForm').submit();" })%><%}%>
下面是使用jQuery的方法
<script type="text/javascript"> $(function() { $("#CategoryID").change(function() { $('#TheForm').submit(); }); });</script><%using (Html.BeginForm("Index", "Home", FormMethod.Post, new { id = "TheForm" })){%> <%=Html.DropDownList("CategoryID", (SelectList) ViewData["Categories"], "--Select One--") %><%}%>
提示
在HtmlHelper中並沒有提供為DropDownList添加提示的重載,提示是通過設定<option>中的title屬性來實現的,當然你可以實現自己的HtmlHelper來通過列表為每個title賦上相應的值,但是這有點麻煩。卻而代之的是,你可以使用jQuery來很容易的實現這點:
<script type="text/javascript"> $(function() { $("#CategoryID option").each(function() { $(this).attr({'title': $(this).html()}); }); });</script>
----------------------------------------------
原文連結:http://www.mikesdotnetting.com/Article/128/Get-The-Drop-On-ASP.NET-MVC-DropDownLists
translated by:CareySon