天天看點

詳解Asp.net MVC DropDownLists

1.

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>      

    上面三個代碼段生成效果相同,如下:

詳解Asp.net MVC DropDownLists

     如果的資料是來自資料庫,那最好還是使用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();
}      
詳解Asp.net MVC DropDownLists

使用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”在清單生成後被選中:

詳解Asp.net MVC DropDownLists

預設值

上面所有例子都會在頁面載入後預設選擇第一個選項,但很多情況下,需要一個預設值來代替第一個值被選擇,這個預設值可以是空或者是提示使用者”請選擇”,或者類似的。DropDownList還有一個重載可以實作這點-public static string DropDownList(this HtmlHelper htmlHelper, string name, IEnumerable<SelectListItem> selectList, string optionLabel).

<%= Html.DropDownList("CategoryID", (SelectList) ViewData["Categories"], "--Select One--") %>      
詳解Asp.net MVC DropDownLists

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>      
詳解Asp.net MVC DropDownLists

----------------------------------------------

原文連結:http://www.mikesdotnetting.com/Article/128/Get-The-Drop-On-ASP.NET-MVC-DropDownLists

2.

MVC3 DropDownList

1.基本使用方法:

(1)Html.DropDownList("Provincex"),其中Provincex為背景設定的ViewBag.Provincex

(2)Html.DropDownList()綁定 object htmlAttribute屬性的方法屬性的設定如new {width="50px"}等,注意的是這裡的必須是最終生成的HTML控件的基本屬性如width、height等也可以是style等。也可以通過使用@來指定屬性例:new {@width=“50px”}

(3)以添加為例,有時在儲存時會出現,無法擷取DropDownList值的情況,這時可以通過在

[HttpPost]

        public ActionResult Create(){}中重新綁定控件值來解決此問題,如果多個Action在同一個Controler中,最好将DropDownList控件的綁定獨立出一個單獨的函數使用。

2.DropDownList與Model驗證共同使用。

(1)在實際使用過程中經常需要在下拉控件初始化時呈現“--請選擇--”字樣,為了能正常使用用戶端腳本驗證,最好如下:

[csharp] view plain copy print ?

  1. <SPAN style="WHITE-SPACE: pre"> </SPAN>private void AddProvinceDll()  
  2.         {  
  3.             IEnumerable<SelectListItem> provinceList = (from c in db.Cities  
  4.                                                         orderby c.city_num  
  5.                                                         select new SelectListItem  
  6.                                                         {  
  7.                                                             Value = c.province,  
  8.                                                             Text = c.province  
  9.                                                         }).Distinct();  
  10.             List<SelectListItem> Items = new List<SelectListItem>();  
  11.             Items.Add(new SelectListItem { Value = "請選擇", Text = "--請選擇--" });  
  12.             Items.AddRange(provinceList);  
  13.             ViewBag.Provincex = Items;              
  14.         }  
private void AddProvinceDll()
        {
            IEnumerable<SelectListItem> provinceList = (from c in db.Cities
                                                        orderby c.city_num
                                                        select new SelectListItem
                                                        {
                                                            Value = c.province,
                                                            Text = c.province
                                                        }).Distinct();
            List<SelectListItem> Items = new List<SelectListItem>();
            Items.Add(new SelectListItem { Value = "請選擇", Text = "--請選擇--" });
            Items.AddRange(provinceList);

            ViewBag.Provincex = Items;            
        }
           

(2)Model驗證

在實際使用時,如果下拉清單選擇為“---請選擇-”時,用戶端做出提示,下拉内容必須填寫。同時為了使用Model中的屬性在這裡是Province,這樣利于MVC自動實作資料傳遞,利于儲存與修改。我們這樣處理,通過使用DropDownListFor實作。

[csharp] view plain copy print ?

  1. <SPAN style="WHITE-SPACE: pre"> </SPAN>@Html.DropDownListFor(model => Model.Province, ViewBag.Provincex as IEnumerable<SelectListItem>)  
@Html.DropDownListFor(model => Model.Province, ViewBag.Provincex as IEnumerable<SelectListItem>)
           

(3)實作model驗證。

首先,自定義Model驗證

[csharp] view plain copy print ?

  1. using System;  
  2. using System.Web.Mvc;  
  3. using System.ComponentModel.DataAnnotations;  
  4. using System.Collections.Generic;  
  5. namespace OnlineApplication.Validator  
  6. {  
  7.     public sealed class NoIsAttribute : ValidationAttribute, IClientValidatable  
  8.     {  
  9.         public string InputString { get; set; }  
  10.         public NoIsAttribute()  
  11.         {  
  12.             ErrorMessage = "驗證失敗";  
  13.         }  
  14.         public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)  
  15.         {  
  16.             ModelClientValidationRule rule = new ModelClientValidationRule  
  17.             {  
  18.                 ValidationType = "nois",  
  19.                 ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())  
  20.             };  
  21.             rule.ValidationParameters["inputstring"] = InputString;  
  22.             yield return rule;  
  23.         }  
  24.         public override bool IsValid(object value)  
  25.         {  
  26.             if (value == null)  
  27.                 return true;  
  28.             string inputString = (string)value;  
  29.             if (inputString.Contains(InputString))  
  30.             {  
  31.                 return false;  
  32.             }  
  33.             return true;  
  34.         }  
  35.     }  
  36. }  
using System;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;

namespace OnlineApplication.Validator
{
    public sealed class NoIsAttribute : ValidationAttribute, IClientValidatable
    {
        public string InputString { get; set; }
        public NoIsAttribute()
        {
            ErrorMessage = "驗證失敗";
        }
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            ModelClientValidationRule rule = new ModelClientValidationRule
            {
                ValidationType = "nois",
                ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
            };
            rule.ValidationParameters["inputstring"] = InputString;
            yield return rule;
        }

        public override bool IsValid(object value)
        {
            if (value == null)
                return true;
            string inputString = (string)value;
            if (inputString.Contains(InputString))
            {
                return false;
            }
            return true;
        }
    }
}
           

然後在Model中添加标簽

[csharp] view plain copy print ?

  1. <SPAN style="WHITE-SPACE: pre"> </SPAN>[Display(Name="所在省份")]  
  2.         [NoIs(InputString = "請選擇", ErrorMessage = "所在省份不能為空")]  
  3.         public string Province { get; set; }  
[Display(Name="所在省份")]
        [NoIs(InputString = "請選擇", ErrorMessage = "所在省份不能為空")]
        public string Province { get; set; }
           

最後在調用的界面中添加如下JS代碼:

[javascript] view plain copy print ?

  1. <script type="text/javascript">  
  2.     $.validator.addMethod("nois", function (value, element, param) {  
  3.         if (value == false) {  
  4.             return true;  
  5.         }  
  6.         if (value.indexOf(param) != -1) {  
  7.             return false;  
  8.         }  
  9.         else {  
  10.             return true;  
  11.         }  
  12.     });  
  13.     $.validator.unobtrusive.adapters.addSingleVal("nois", "inputstring");  
  14. </script>  
<script type="text/javascript">
    $.validator.addMethod("nois", function (value, element, param) {
        if (value == false) {
            return true;
        }
        if (value.indexOf(param) != -1) {
            return false;
        }
        else {
            return true;
        }
    });
    $.validator.unobtrusive.adapters.addSingleVal("nois", "inputstring");
</script>
           

這樣就能使用自帶的Model驗證實作用戶端驗證了。

繼續閱讀