在ASP.NET MVC中,儘管我們可以直接在頁面中編寫HTML控制項,並綁定控制項的屬性,但更方便的辦法還是使用HtmlHelper中的輔助方法。在View中,包含一個類型為HtmlHelper的屬性Html,它為我們呈現控制項提供了捷徑。 我們今天主要來討論Html.DropDownList的用法,首 ...
在ASP.NET MVC中,儘管我們可以直接在頁面中編寫HTML控制項,並綁定控制項的屬性,但更方便的辦法還是使用HtmlHelper中的輔助方法。在View中,包含一個類型為HtmlHelper的屬性Html,它為我們呈現控制項提供了捷徑。
我們今天主要來討論Html.DropDownList的用法,首先從Html.TextBox開始。
Html.TextBox有一個重載方法形式如下:
public static string TextBox(this HtmlHelper htmlHelper, string name, object value);
其中name參數為文本框name屬性(以及id屬性)的值,value參數為文本框的預設值(即value屬性的值)。如果value參數為null或者使用沒有value參數的重載方法,那麼此時name參數同時還是一個鍵值,負責獲取文本框的預設值。獲取的順序為,先從ViewData中查找是否存在鍵值為name值的項,如果ViewData中沒有則從ViewData.Model中查找是否存在名稱為name值的屬性,如果仍然不存在,則返回null。(具體參見HtmlHelper的InputHelper輔助方法)
也就是說
public ActionResult Test()
{
ViewData["Name"] = "Jade";
return View();
}
<%= Html.TextBox("Name")%>
這樣的代碼將會輸出這樣的HTML:
<input id="Name" name="Name" type="text" value="Jade" />
由於TextBox的id和name屬性的值與ViewData中的某一項同名(均為Name),因此TextBox的value屬性的值將自動綁定為ViewData中Name項的值。不僅是ViewData,如果view model的類型包含Name屬性,也將輸出同樣的結果:
var user = new User { Name = "Jade" };
ViewData.Model = user;
return View();
如果ViewData和ViewData.Model中同時存在Name,則優先使用ViewData中的項。
CheckBox、Hidden、Password、RedioButton等控制項也是如此,它們與TextBox一樣都使用input標記,屬性綁定的規則大致相同。
DropDownList則與TextBox等控制項不同,它使用的是select標記。它需要兩個值:在下拉框中顯示的列表,和預設選項。而自動綁定一次只能綁定一個屬性,因此你需要根據需要選擇是綁定列表,還是預設選項。
DropDownList擴展方法的各個重載版本“基本上”都會傳遞到這個方法上:
public static string DropDownList(this HtmlHelper htmlHelper,
string name,
IEnumerable<SelectListItem> selectList,
string optionLabel,
IDictionary<string, object> htmlAttributes) {
…
}
如果沒有指定selectList,該方法將自動綁定列表,即從ViewData中查找name所對應的值。如果提供了selectList,將自動綁定預設選項,即從selectList中找到Selected屬性為true的SelectedListItem。(具體參見HtmlHelper方法的SelectInternal輔助方法)
例1:如果在Action方法中有如下代碼:
List<SelectListItem> items = new List<SelectListItem>();
items.Add(new SelectListItem { Text = "Kirin", Value = "29" });
items.Add(new SelectListItem { Text = "Jade", Value = "28", Selected = true});
items.Add(new SelectListItem { Text = "Yao", Value = "24"});
this.ViewData["list"] = items;
在View中這樣使用:
<%=Html.DropDownList("list")%>
那麼輔助方法將率先從ViewData中獲取key為list的項,如果該項為IEnumerable<SelectedListItem>類型則綁定到下拉框中,否則將拋出InvalidOperationException。由於第二個SelectListItem的Selected為true,則預設選中第二個。
例2:如果Action中代碼如下:
List<SelectListItem> items = new List<SelectListItem>();
items.Add(new SelectListItem { Text = "Kirin", Value = "29" });
items.Add(new SelectListItem { Text = "Jade", Value = "28"});
items.Add(new SelectListItem { Text = "Yao", Value = "24"});
this.ViewData["list"] = items;
this.ViewData["selected"] = 24;
View中的代碼如下:
<%=Html.DropDownList("selected", ViewData["list"] as IEnumerable<SelectListItem>)%>
那麼輔助方法將ViewData["list"]綁定為下拉框,然後從ViewData中獲取key為selected的項,並將下list中Value值與該項的值相等的SelecteListItem設為預設選中項。
以上兩種方法儘管可以實現DropDownList的正確顯示,但並非最佳實踐。在實際項目中,我們更希望在代碼中使用強類型。例如上面兩例中,SelectListItem的Text和Value本來是User對象的Name和Age屬性,然而上面的代碼卻絲毫體現不出這種對應關係。如果User列表是從資料庫或其他外部資源中獲得的,我們難道要用這樣的方式來綁定嗎?
var users = GetUsers();
foreach (var user in users)
{
items.Add(new SelectListItem { Text = user.Name, Value = user.Age.ToString() });
}
這顯然是我們所無法容忍的。那麼什麼是最佳實踐呢?
ASP.NET MVC為DropDownList和ListBox(都在html中使用select標記)準備了一個輔助類型:SelectList。SelectList繼承自MultiSelectList,而後者實現了IEnumerable<SelectListItem>。也就是說,SelectList可以直接作為Html.DropDownList方法的第二個參數。
MultiSelectList包含四個屬性,分別為:
- Items:用於在select標記中出現的列表,通常使用option標記表示。IEnumerable類型。
- DataTextField:作為option的text項,string類型。
- DataValueField:作為option的value項,string類型。
- SelectedValues:選中項的value值,IEnumerable類型。
顯然,作為DropDownList來說,選中項不可能為IEnumerable,因此SelectList提供了一個新的屬性:
- SelectedValue:選中項的value值,object類型。
同時,SelectList的構造函數如下所示:
public SelectList(IEnumerable items, string dataValueField, string dataTextField, object selectedValue)
: base(items, dataValueField, dataTextField, ToEnumerable(selectedValue)) {
SelectedValue = selectedValue;
}
於是我們的代碼變為:
var users = GetUsers();
var selectList = new SelectList(users, "Age", "Name", "24");
this.ViewData["list"] = selectList;
<%=Html.DropDownList("list")%>
當然,你也可以使用不帶selectedValue參數的構造函數重載,而在view中顯式指定IEnumerable<SelectListItem>,併在ViewData或view model中指定其他與DropDownList同名的項作為預設選項。
最後讓我們來回顧一下DropDownList的三種用法:
- 建立IEnumerable<SelectListItem>併在其中指定預設選中項。
- 建立IEnumerable<SelectListItem>,在單獨的ViewData項或view model的屬性中指定預設選中項。
- 使用SelectList。
- 到此結束
- 原創作者:麒麟.NET