2011-01-18 6 views
29

Ten problem dręczy mnie od dwóch dni. Jest kilka podobnych postów, ale żaden nie rozwiązuje całkowicie mojego problemu.Model zawierający listę modeli (MVC-3, Razor)

Stosując MVC 3, żyletka Składnia

- 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)); 
    } 
} 

- ThumbnailModel 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; } 
} 

Więc w czym problem? Cóż, kiedy "Complete Edit!" Naciśnięcie przycisku powoduje wywołanie edycji MyController, zgodnie z oczekiwaniami dla wszystkich danych MyMainModle ... z wyjątkiem listy ThumbnailModel - te okazują się zerowe.

Jak to zrobić? Próbowałem wielu różnych podejść do tego, włączając w to tworzenie edytowalnego szablonu i użycie EditFor (o => ... all to no avail (stało się to mylące, ponieważ nie wiedziałem, czy EditFor miał być dla całej kolekcji czy po prostu pojedynczy element w kolekcji - próbowałem w obie strony) Wszystkie były używane do momentu dodania złożoności pola wyboru do usunięcia, dlatego też konieczne jest pobranie listy miniaturowych modeli w celu sprawdzenia wewnętrznej wartości Usuń wartość. wszystkich do czytania i próbuje zrozumieć to

. [Zastrzeżone -.. niektóre nazwy zmiennych i metody zostały zmienione w celu ochrony niewinnych programu dużo kodu została zabrana i zastąpiona kodem komentarz]

+0

Czy nie powinno to być "thumbnail => thumbnail.Delete"? – Buildstarted

Odpowiedz

45

Oto przykład, że włożyłam do zilustrowania niektórych pojęć:

Model:

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; } 
} 

Kontroler:

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 
    } 
} 

Widok:

@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!" /> 
} 

szablon Redaktor: (~/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

Doskonale! To działa!! Dziękuję bardzo - to bardzo pomocne. Ostatnią rzeczą, którą próbuję uzyskać do pracy z tym przykładem, jest to, że mam nieco bardziej złożony układ dla każdego z ThumbnailModels. W moim oryginalnym kodzie używam czegoś podobnego do @foreach (miniaturka var w Model.ThumbnailImagePathAndNames) ... Wygląda na to, że nie mogę umieścić mojego układu (limitu kolumnowego) kodu wokół edycji dla i, a następnie użyć @ Html.EditorFor (x => miniaturka). Czy wiesz, jak mogłem uzyskać tę drobiazgową kontrolę? W szablonie jakoś umieścić @model IEnumerable na górze? Dzięki! – Rob

+0

** Być może będę musiał przenieść powyższe pytanie do nowego wątku. Aby sparafrazować, chciałbym mieć większą kontrolę nad @ Html.EditorFor, używając mojego własnego @Foreach do obsługi każdego modelu osobno, zamiast pozwalać na przepuszczenie .NET i renderowanie go automatycznie.Zmiana szablonu edytora w celu użycia funkcji @model IEnumerable i wdrożenie funkcji @foreach w ramach programu okazało się nieskuteczne. – Rob

+0

@Rob, nie rozumiem, jaki rodzaj kontroli musisz mieć. W twoim przykładzie właśnie przechodzisz przez kolekcję i dla każdego elementu wyprowadzasz kilka pól wejściowych. EditorFor powinien wystarczyć, aby uniknąć pisania tego wszystkiego. –