2011-01-18 13 views
29

Este problema me ha estado plagando durante dos días. Hay algunas publicaciones similares, pero ninguna que solucione mi problema por completo.Modelo que contiene la lista de modelos (MVC-3, Razor)

Usando MVC-3, la maquinilla de afeitar sintaxis:

- EDIT.cshtml -

@using (Html.BeginForm("Edit", "My", FormMethod.Post, new { enctype = "multipart/form-data" })) 
{ 
    <!-- Some fields... --> 
    <div class="editor-field"> 
     @Html.TextAreaFor(m => m.LongDescription) 
     @Html.ValidationMessageFor(m => m.LongDescription) 
    </div> 

    <!-- Some more fields work... Including picture upload (summary).--> 
    <input name="button" type="submit" value="Add Picture" /> 

    <!-- Picture Item display --> 
    @foreach(var thumbnail in Model.ThumbnailImagePathAndNames) 
    { 
     <img src="@Url.Content(@thumbnail.ThumbnailPicturePath)" alt="" width="200" /> 
     @Html.RadioButtonFor(o=>o.SelectedImage, @thumbnail.ImageGUID) Primary Picture 
     <!-- Checkbox to mark for deletion --> 
     @Html.CheckBoxFor(o=>thumbnail.Delete) Delete ???????? <!---- Here is a problem - I don't understand how this should work --> 
    } 
    <input id="Submit1" name="button" type="submit" value="Complete Edit!" /> 
} 

- MyController.cs -

[HttpPost] 
public ActionResult Edit(String button, HttpPostedFileBase file, MyMainModel model) 
{ 
    // if button = submit picture, work with picture here and break(long story) 

    // save model data 
     // if valid, save and redirect 


    // not valid or error, load up view like normal but with error messages 
    model.LoadThumbnails(); 
    return View(model); 

} 

- MyMainModel.cs - -

public class MyMainModel 
{ 
    // some properties... 
    public Guid? SelectedImage { get; set; } 

    [Display(Name = "Detailed Description")] 
    public String LongDescription { get; set; } 

    // some more properties.... 


    // and finally my list of models 
    public IList<ThumbnailModel> ThumbnailImagePathAndNames { get; set; } 

    public void LoadThumbnails() 
    { 
     // load up initial thumbnail models 
     this.ThumbnailImagePathAndNames = new List<ThumbnailModel>(readDataService.GetThumbnailModels(this.SomeID)); 
    } 
} 

- MiniaturaModelo s.cs -

public class ThumbnailModel 
{ 
    public Guid ImageGUID { get; set; } 
    public String FullSizePicturePath { get; set; } 
    public String ThumbnailPicturePath { get; set; } 

    public bool Delete { get; set; } 
} 

¿Cuál es el problema? Bueno, cuando la "Edición completa!" se presiona el botón, se llama a Editar de MyController, como se esperaba, con todos los datos de MyMainModle intactos ... excepto por la lista de MiniaturaModelo, que resulta ser nula.

¿Cómo se supone que se debe hacer? He intentado muchos enfoques diferentes para esto, incluida la creación de una plantilla editable y el uso de EditFor (o => ... todo en vano (esto se volvió confuso ya que no sabía si se suponía que el EditFor era para toda la colección o simplemente un único elemento en la colección - Intenté en ambos sentidos). Todo solía funcionar hasta que agregué la complejidad de la casilla de verificación para su eliminación, por lo tanto, necesitaba recuperar la lista de MiniaturaModelos para verificar ese valor interno de la propiedad Eliminar

Gracias todos por leer y tratar de entender este

. [Renuncia -.. algunos nombres de variables y métodos han sido cambiados para proteger el programa inocente Una gran cantidad de código ha sido despojado de distancia y reemplazado por código comentario]

+0

¿No debería ser 'thumbnail => thumbnail.Delete'? – Buildstarted

Respuesta

45

He aquí un ejemplo que he puesto para ilustrar algunos conceptos:

Modelo:

public class MyMainModel 
{ 
    public Guid? SelectedImage { get; set; } 
    public string LongDescription { get; set; } 

    public IEnumerable<ThumbnailModel> ThumbnailImagePathAndNames { get; set; } 

    public HttpPostedFileBase File { get; set; } 
} 

public class ThumbnailModel 
{ 
    public Guid ImageGUID { get; set; } 
    public bool Delete { get; set; } 
} 

controlador:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new MyMainModel 
     { 
      // TODO: fetch from the repository instead of hardcoding 
      ThumbnailImagePathAndNames = new[] 
      { 
       new ThumbnailModel { ImageGUID = Guid.NewGuid() }, 
       new ThumbnailModel { ImageGUID = Guid.NewGuid() }, 
       new ThumbnailModel { ImageGUID = Guid.NewGuid() }, 
      } 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(MyMainModel model) 
    { 
     ... the model will be properly bound here 
    } 
} 

Vista:

@model AppName.Models.MyMainModel 
@{ 
    ViewBag.Title = "Index"; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 
@using (Html.BeginForm("index", "home", FormMethod.Post, new { enctype = "multipart/form-data" })) 
{ 
    <div class="editor-field"> 
     @Html.TextAreaFor(m => m.LongDescription) 
     @Html.ValidationMessageFor(m => m.LongDescription) 
    </div> 
    <input type="file" name="file" /> 
    <!-- Use different names for the upload and complete submit 
     buttons so that you can distinguish which one was clicked 
     in the POST action 
    --> 
    <input name="upload" type="submit" value="Add Picture" /> 

    @Html.EditorFor(x => x.ThumbnailImagePathAndNames)  
    <input name="complete" type="submit" value="Complete Edit!" /> 
} 

editor de plantillas: (~/Views/Home/EditorTemplates/ThumbnailModel.cshtml):

@model AppName.Models.ThumbnailModel 
<!-- Pass the image id as hidden field --> 
@Html.HiddenFor(x => x.ImageGUID) 
@Html.CheckBoxFor(x => x.Delete) 
+0

¡Excelente! ¡¡Funciona!! Muchas gracias, eso es extremadamente útil. Lo último que intento hacer para trabajar con este ejemplo es que tengo un diseño algo más complejo para cada uno de los MiniaturaModelos. En mi código original, uso algo como @foreach (var thumbnail en Model.ThumbnailImagePathAndNames) ... Parece que no puedo poner mi código de diseño (cosas de límite de columna) alrededor de la edición para y luego usar @ Html.EditorFor (x => miniatura). ¿Sabes cómo podría obtener este control de grano fino? En la plantilla, de alguna forma, coloque @model IEnumerable en la parte superior. ¡Gracias! – Rob

+0

** Es posible que deba mover la pregunta anterior a un nuevo hilo. Parafraseando, me gustaría tener más control sobre @ Html.EditorFor, usando mi propio @Foreach manejando cada modelo por separado, en lugar de dejar que .NET entre en loop y lo renderice automáticamente.Cambiar la plantilla del editor para tomar un @model IEnumerable e implementar el @foreach dentro de este ha resultado infructuoso. – Rob

+0

@Rob, no entiendo qué tipo de control necesita tener. En su ejemplo, solo está recorriendo la colección y para cada elemento genera un par de campos de entrada. EditorFor debería ser suficiente para evitar que escriba todo esto. –

Cuestiones relacionadas