MVC dropdownlist 后端設置select屬性后前端依然不能默認選中的解決方法


 

-----------------------------------來自網上的解決方法---------------------------------------------

ASP.Net MVC的ViewBag一個坑,不要跳進去
如鵬的學習管理系統是使用ASP.net MVC 5開發的,今天一個新版本發布后網站出現一個Bug,學生在下拉列表中選中的項再加載顯示的時候發現仍然沒被選中。詳細一點說吧:
假如有這樣一個Action:
public ActionResult Index(){List persons = new List();persons.Add(new SelectListItem { Text = "騰訊", Value = "qq" });persons.Add(new SelectListItem { Text = "如鵬", Value = "rupeng", Selected = true });ViewBag.persons = persons;return View();}
Cshtml是這樣的:
@Html.DropDownList("persons", (IEnumerable)ViewBag.persons)
生成的html是這樣的:
騰訊如鵬
  竟然第二項沒有處於選中狀態,太詭異了吧!
只要把DropDownList第二個參數的"persons"改成和”ViewBag.persons”的persons名字不一樣就可以,比如:
@Html.DropDownList("persons1", (IEnumerable)ViewBag.persons)
這樣就正確生成了:
騰訊如鵬
  
好詭異!!!

咋辦?看源碼!
DropDownList是定義在SelectExtensions擴展類中,DropDownList方法最終是調用SelectInternal方法,核心代碼是這一段:
if (!flag && obj == null && !string.IsNullOrEmpty(name)){obj = htmlHelper.ViewData.Eval(name);}if (obj != null){selectList = SelectExtensions.GetSelectListWithDefaultValue(selectList, obj, allowMultiple);}
  
這個name參數就是我們傳遞給DropDownList的第一個參數"persons",上面代碼主要邏輯就是:首先到ViewData中查找名字為"persons"的值,我們知道ViewData和ViewBag是一樣的,所以htmlHelper.ViewData.Eval(name)取到的值就是我們在Index中定義的List()集合。GetSelectListWithDefaultValue方法的代碼是:
private static IEnumerable GetSelectListWithDefaultValue(IEnumerable selectList, object defaultValue, bool allowMultiple){IEnumerable enumerable= new object[]{defaultValue};IEnumerable collection =from object value in enumerableselect Convert.ToString(value, CultureInfo.CurrentCulture);HashSet hashSet = new HashSet(collection, StringComparer.OrdinalIgnoreCase);List list = new List();foreach (SelectListItem current in selectList){current.Selected = ((current.Value != null) ? hashSet.Contains(current.Value) : hashSet.Contains(current.Text));list.Add(current);}return list;}
  
注意,我們的List()集合被當成defaultValue參數傳遞給GetSelectListWithDefaultValue方法了(why?),在方法內部又把defaultValue給 Convert.ToString()一下,變成了”System.Collections.Generic.List`1[System.Web.Mvc.SelectListItem]”這么一個玩意, GetSelectListWithDefaultValue的主要邏輯就是查找selectList中等於”System.Collections.Generic.List`1[System.Web.Mvc.SelectListItem]”的值,能找到才算見了鬼呢!!!
經過上面的分析我們還可以知道,不能讓cshtml中DropDownList的第一個name參數和ViewBag中任何一個屬性重名,否則還是會有問題,比如
public ActionResult Index(){List persons = new List();persons.Add(new SelectListItem { Text = "騰訊", Value = "qq" });persons.Add(new SelectListItem { Text = "如鵬", Value = "rupeng", Selected = true });ViewBag.persons = persons;ViewBag.persons1 = new string[] { };return View();}
  
Cshtml如下:
@Html.DropDownList("persons1", (IEnumerable)ViewBag.persons)
生成的html中第二條數據照樣不會被selected
不知道微軟為什么把DropDownList這么簡單的一個東西搞的這么復雜,正驗證了這句話“寫的越多,錯的越多”。當然也許微軟會給出理由說我們用錯了,說“It’s not a bug,It’s a feature,by design”好吧!謝特!
5樓高卿這代碼,有點眼熟,,,不過盡量不用viewbag的話。。那也就viewdata的了。或者其他前端框架了。4樓Choo正確的用法是:@Html.DropDownList(quot;personsquot;, null),,這樣的寫法方便性體現在DropDownListFor時,model對應屬性的值就會自動被選上,而不需要在構建SelectList時去確定被選值。3樓幻天芒想想也是這個問題,不過暫時沒想到有說買更好的方式實現...Re: 高卿@幻天芒,親。有個麻煩的問題麻煩下您。您能給我一個QQ么。關於rsa加密java和C#之間的問題。2樓小眼睛老鼠這是mvc的特性啊,也就是說 前端的控件 都會通過key 去viewdata 或者 viewbag作為當前控件的value,,也就是說如果你要設置 某個控件 例如 control1的value的話,那么只要在action中寫成這樣就好了,viewbag. control1 = ???,前端不用再在 控件里面賦值了,,這里你正好吧value當做了dropdownlist的 內部結構數據傳進去了,,所以就。。。。。Re: 楊中科@小眼睛老鼠,引用這是mvc的特性啊,也就是說 前端的控件 都會通過key 去viewdata 或者 viewbag作為當前控件的value,,也就是說如果你要設置 某個控件 例如 control1的value的話,那么只要在action中寫成這樣就好了,viewbag. control1 = ???,前端不用再在 控件里面賦值了,,這里你正好吧value當做了dropdownlist的 內部結構數據傳進去了,,所以就。。。。。,如果這樣的話就太惡心了,Razor做好模板引擎的工作就行了,傳給你數據、你負責展現,別搞這么多自動化的東西。架構設計的一個原則就是“Keep it simple”1樓a.thinker約定

大於配置 ,所以,你要確定asp.mvc約定了什么,,你可以試下另一種寫法:,代碼,var persons = new Listlt;objectgt; { new { Text = quot;騰訊quot;, Value = quot;qqquot;

 

 

 

 

 

 

 

 

 

 

-----------------------------------來自網上的解決方法---------------------------------------------

 

 

----------------------------------------自己的代碼-------------------------------------------------

 

 

 

---------------------------------------自己的代碼---------------------------------------

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。