2011-03-01 75 views
1

我想綁定到具有集合屬性(特別是List)的模型。對於這個例子的目的,這代表用戶角色的列表:MVC - 使用自定義模板將數據綁定到集合的問題

public class RolesModel 
{ 
    private List<SelectListItem> _Roles = null; 
    public string Name { get; set; } 
    public List<SelectListItem> Roles 
    { 
     get { 
     if (_Roles == null) { _Roles = new List<SelectListItem>(); } 
     return _Roles; 
     } 
     set { _Roles = value; } 
    } 
} 

我通過以下控制器結合這一個強類型的視圖:

public class TestController : Controller 
{ 
    RolesModel myModel = new RolesModel(); 

    [HttpGet] 
    public ActionResult Edit() 
    { 
     myModel.Name = "Joe Bloggs"; 
     myModel.Roles = new List<SelectListItem> 
     { 
     new SelectListItem { Value = "1", Text = "Member", Selected = true }, 
     new SelectListItem { Value = "2", Text = "Manager", Selected = true }, 
     new SelectListItem { Value = "3", Text = "Administrator", Selected = false } 
     }; 

     return View(myModel); 
    } 


    [HttpPost] 
    public ActionResult Edit(RolesModel m) 
    { 
     // !!! m.Roles is always empty !!! 
     return View("Results", m); 
    } 
} 

這然後調用下面的視圖:

@model MyProject.WebUI.Models.RolesModel 
@using (Html.BeginForm()) 
{ 
    <p> 
     @Html.LabelFor(m => m.Name) 
     @Html.EditorFor(m => m.Name) 
    </p>        
    <div> 
     @Html.EditorFor(m => m.Roles, "CheckBoxList") 
    </div>        
    <p> 
     <input type="submit" value="Save" /> 
    </p> 
} 

注意要在「/Views/Shared/EditorTemplates/CheckBoxList.cshtml」我的自定義編輯模板,該模板特定呼叫,這看起來是這樣的:

@model List<System.Web.Mvc.SelectListItem> 

<h3>Type: @Html.LabelFor(m => m)</h3> 
<ul> 
    @for (int i = 0; i < Model.Count; i++) 
    { 
     <li> 
     @Html.CheckBoxFor(m => m[i].Selected) 
     @Html.LabelFor(m => m[i].Selected, Model[i].Text) 
     @Html.HiddenFor(m => m[i].Value) 
     </li> 
    } 
</ul> 

這個想法是,每個SelectListItem都由循環呈現的Html表示。

過程的第一部分似乎正常工作,呈現形式爲正常現象,可更新的「名稱」文本框中,並檢查/取消選中的複選框。

問題是,當表單回發給控制器時,Roles集合從未被填充。

我是新來的MVC,並認爲該框架實際上是通過強制執行表單元素命名約定重新構建從崗位模型數據。我顯然錯過了一個重要的觀點,我希望有人能夠指引我走向正確的方向。

謝謝,併爲長期職位道歉。

回答

5

這裏是你如何才能夠着手:

@model MyProject.WebUI.Models.RolesModel 
@using (Html.BeginForm()) 
{ 
    <p> 
     @Html.LabelFor(m => m.Name) 
     @Html.EditorFor(m => m.Name) 
    </p>        
    <div> 
     <ul> 
      @Html.EditorFor(m => m.Roles) 
     </ul> 
    </div>        
    <p> 
     <input type="submit" value="Save" /> 
    </p> 
} 

和EditorTemplate(/Views/Shared/EditorTemplates/SelectListItem.cshtml)內:

@model System.Web.Mvc.SelectListItem 
<h3>Type: @Html.LabelFor(m => m)</h3> 
<li> 
    @Html.CheckBoxFor(m => m.Selected) 
    @Html.LabelFor(m => m.Selected, Model.Text) 
    @Html.HiddenFor(m => m.Value) 
</li> 

通知編輯模板的簡化。它不再需要List<SelectListItem>作爲模型,而只是SelectListItem。它將自動爲Roles集合的每個元素調用,這樣就不需要編寫任何循環。只要按照約定。

我也將簡化您的視圖模型是這樣的:

public class RolesModel 
{ 
    public string Name { get; set; } 
    public IEnumerable<SelectListItem> Roles { get; set; } 
} 

和控制器:

public class TestController : Controller 
{ 
    public ActionResult Edit() 
    { 
     var myModel = new RolesModel 
     { 
      Name = "Joe Bloggs", 
      Roles = new[] 
      { 
       new SelectListItem { Value = "1", Text = "Member", Selected = true }, 
       new SelectListItem { Value = "2", Text = "Manager", Selected = true }, 
       new SelectListItem { Value = "3", Text = "Administrator", Selected = false } 
      } 
     }; 
     return View(myModel); 
    } 

    [HttpPost] 
    public ActionResult Edit(RolesModel m) 
    { 
     // m.Roles should be correctly bound 
     return View("Results", m); 
    } 
} 
+0

這工作很漂亮,和這麼幹淨 - 這是很難相信這是所有需要的代碼!非常感謝您的幫助 - 非常感謝 – Neilski 2011-03-01 15:49:28