2011-12-22 15 views
9

Realmente estoy luchando para envolver mi cabeza alrededor de esto:¿Cómo puedo enlazar casillas de verificación a un modelo de vista en MVC3

Tengo un UserModel y una UserRoleModel:

public class UserModel 
{ 
    [Required] 
    [Display(Name = "User name")] 
    public string UserName { get; set; } 

    [Required] 
    [DataType(DataType.EmailAddress)] 
    [Display(Name = "Email address")] 
    public string Email { get; set; } 

    [Required] 
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 
    [DataType(DataType.Password)] 
    [Display(Name = "Password")] 
    public string Password { get; set; } 

    [DataType(DataType.Password)] 
    [Display(Name = "Confirm password")] 
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 
    public string ConfirmPassword { get; set; } 

    public IEnumerable<string> UserRoles { get; set; } 
} 
public class UserRoleModel 
{ 
    public IEnumerable<string> AllRoles { get; set; } 
    public UserModel user { get; set; } 

    public UserRoleModel() 
    { 
     this.AllRoles = Roles.GetAllRoles(); 
     this.user = new UserModel(); 
    } 
} 

En el controlador:

 public ActionResult Create() 
    { 
     return View(new UserRoleModel()); 
    } 

    [HttpPost] 
    public ActionResult Create(UserRoleModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      MembershipCreateStatus createStatus; 
      Membership.CreateUser(model.user.UserName, model.user.Password, model.user.Email, null, null, true, null, out createStatus); 

      if (createStatus == MembershipCreateStatus.Success) 
      { 
       foreach (var r in model.AllRoles) 
       { 
        Roles.AddUserToRole(model.user.UserName, r); 
       } 

       return RedirectToAction("Index", "Home"); 
      } 
      else 
      { 
       ModelState.AddModelError("", ErrorCodeToString(createStatus)); 
      } 
     } 

     return View(model); 
    } 

Y la vista:

@model BBmvc.Areas.Tools.Models.UserRoleModel 

y:

@using (Html.BeginForm()) { 
@Html.ValidationSummary(true) 
<fieldset> 
    <legend>UserModel</legend> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.user.UserName) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.user.UserName) 
     @Html.ValidationMessageFor(model => model.user.UserName) 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.user.Email) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.user.Email) 
     @Html.ValidationMessageFor(model => model.user.Email) 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.user.Password) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.user.Password) 
     @Html.ValidationMessageFor(model => model.user.Password) 
    </div> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.user.ConfirmPassword) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.user.ConfirmPassword) 
     @Html.ValidationMessageFor(model => model.user.ConfirmPassword) 
    </div> 
    <div class="editor-field"> 
     @foreach (var r in @Model.AllRoles) 
     { 
      @Html.CheckBox(r,false) 
      @Html.Label(r) 
      <br /> 
     } 
    </div> 

    <p> 
     <input type="submit" value="Create" /> 
    </p> 
</fieldset> 

}

En primer lugar, no he sido capaz de averiguar cómo utilizar CheckBoxFor de mi modelo de vista. Pero muestra las opciones de casilla de verificación, así que puedo vivir con eso. Pero no puedo averiguar cómo determinar qué casillas de verificación se marcaron cuando se publicó el formulario. También parece haber roto la validación del lado del cliente, supongo porque estoy usando un viewModel.

Respuesta

13

El ayudante CheckBoxFor funciona con propiedades booleanas. Así se podría definir una vista de modelo:

public class RoleViewModel 
{ 
    public string Name { get; set; } 
    public bool Selected { get; set; } 
} 

y luego modificar la propiedad AllRoles en su modelo de vista:

public class UserRoleModel 
{ 
    public IEnumerable<RoleViewModel> AllRoles { get; set; } 
    public UserModel user { get; set; } 

    public UserRoleModel() 
    { 
     this.AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel 
     { 
      Name = r 
     }); 
     this.user = new UserModel(); 
    } 
} 

y en la vista en lugar de escribir foreach bucles utilizar un editor de plantillas:

<div class="editor-field"> 
    @Html.EditorFor(x => x.AllRoles) 
</div> 

y finalmente define una plantilla de editor para el tipo RoleViewModel que se representará automáticamente para cada elemento del AllRoles colección (~/Views/Shared/EditorTemplates/RoleViewModel.cshtml)

@model RoleViewModel 
@Html.CheckBoxFor(x => x.Selected) 
@Html.LabelFor(x => x.Selected, Model.Name) 
@Html.HiddenFor(x => x.Name) 
<br /> 

Y eso es todo. Dentro de la acción Publicar obtendrá la propiedad AllRoles poblada con los valores.

+1

En la acción posterior, la propiedad AllRoles.Selected siempre se establece en false, independientemente de si se marcaron o no casillas de verificación. – Rob

0

Como Rob mencionó en la respuesta anterior, todas las propiedades seleccionadas serán falsas. Utilicé este fragmento de código para cubrir eso.

AllRoles = Roles.GetAllRoles().Select(r => new RoleViewModel() 
{ 
    Name = r, 
    Selected = Roles.GetRolesForUser(uvm.UserProfile.UserName).Contains(r) ? true : false 
}); 
Cuestiones relacionadas