MVC - 使用自定义模板将数据绑定到集合的问题

MVC - 使用自定义模板将数据绑定到集合的问题

问题描述:

我想绑定到具有集合属性(特别是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,并认为该框架实际上是通过强制执行表单元素命名约定重新构建从岗位模型数据。我显然错过了一个重要的观点,我希望有人能够指引我走向正确的方向。

谢谢,并为长期职位道歉。

这里是你如何才能够着手:

@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