2012-10-02 24 views
8

Mam następujący układ klasa w MVC:MVC - Edycja listy obiektów

public class ReportModel 
{ 
    List<SomeItem> items; 
    string value; 
    string anotherValue; 
} 

teraz utworzyć silnie typami widoku w MVC tego typu i dokonać edytowalnych pól tekstowych, aby edytować każdą wartość, jak również użyj pętli foreach do wypełnienia pól tekstowych, aby edytować elementy na liście someitem.

Po przesłaniu do metody httppost wartości jednostkowe wrócą poprawnie w obiekcie obiektu raportu, ale lista nie zostanie zwrócona w obiekcie. Jak to zrobić?

Kiedy mówię HttpPost ja odnoszę się do metody, która MVC jest księgowanie powrotem do

[HttpPost] 
public ActionResult EditReport(ReportModel report) 
{ 
    // Save the report in here after the update on the UI side 
} 

widoku kodu do opublikowania listy someitem

if (Model.items != null && Model.items.Count > 0) 
{ 
    for (int i = 0; i < Model.items.Count; i++) 
    {     
     <div class="editrow"> 
      <div class="edititem"> 
       <div class="editor-label"> 
        @Html.LabelFor(m => m.items.ElementAt(i).propertyOne) 
       </div> 
       <div class="editor-field"> 
        @Html.TextBoxFor(m => m.items.ElementAt(i).propertyOne) 
        @Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyOne) 
       </div> 
      </div> 
      <div class="edititem"> 
       <div class="editor-label"> 
        @Html.LabelFor(m => m.items.ElementAt(i).propertyTwo) 
       </div> 
       <div class="editor-field"> 
        @Html.TextBoxFor(m => m.items.ElementAt(i).propertyTwo) 
        @Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyTwo) 
       </div> 
      </div> 
      <div class="edititem"> 
       <div class="editor-label"> 
        @Html.LabelFor(m => m.items.ElementAt(i).propertyThree) 
       </div> 
       <div class="editor-field"> 
        @Html.TextBoxFor(m => m.items.ElementAt(i).propertyThree) 
        @Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyThree) 
       </div> 
      </div> 
     </div> 
    } 
} 
+0

Po pierwsze: Nitpicking: W tytule: lista, nie świeci. Po drugie: Jaka jest metoda httppost, o której mówisz? Czy mówimy tu o Androidzie? Dodaj ten tag, aby go oznaczyć. – bldoron

+6

Czy przeczytałeś na ten temat: http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx –

+0

@ KirirBestemyanov Nie jest to dokładnie to, czego szukam, ponieważ spodziewam się przywrócić je do modelu raportu, nie jako osobne parametry do funkcja – DMCApps

Odpowiedz

1

odniesienia Cyryla do wpisu na blogu Scotta Hanselman jest poprawne, ale czytasz to zbyt wąsko. W pokazanym przykładzie przekazuje tablicę do metody działania, ale równie dobrze można ją zawrzeć w modelu macierzystym. Ta sama koncepcja ma zastosowanie.

Należy jednak wiedzieć, że domyślny segregator modelu nie tworzy instancji klas zagnieżdżonych, więc nie utworzy instancji klasy List, co oznacza, że ​​zawsze będzie miała wartość NULL. Aby to naprawić, musisz utworzyć instancję pustej klasy list w konstruktorze.

Jest to tylko część problemu, ponieważ dane muszą być sformatowane we właściwy sposób, aby spoina modelu mogła je powiązać. W tym miejscu pojawia się wpis na blogu Scotta, ponieważ zapewnia format wymagany dla segregatora modelu do rozpoznawania danych jako listy.

Jest to zwykle obsługiwane, jeśli używasz edytora EditorTemplate i używasz Html.EditorFor (m => m.Items), a następnie masz SomeItem.cshtml EditorTemplate. Zajmuje się problematyką nazewnictwa kolekcji przedmiotów (o ile używasz również silnie wpisanych helperów w szablonie).

11

Nie używaj ElementAt(1) w wyrażeniach lambda => to rujnuje twoje nazwy pól wejściowych. Przeczytaj post na blogu, który zaproponował ci Kirill.

Więc można użyć indeksowanych dostęp:

for (int i = 0; i < Model.items.Count; i++) 
{     
    <div class="editrow"> 
     <div class="edititem"> 
      <div class="editor-label"> 
       @Html.LabelFor(m => m.items[i].propertyOne) 
      </div> 
      <div class="editor-field"> 
       @Html.TextBoxFor(m => m.items[i].propertyOne) 
       @Html.ValidationMessageFor(m => m.items[i].propertyOne) 
      </div> 
     </div> 
     <div class="edititem"> 
      <div class="editor-label"> 
       @Html.LabelFor(m => m.items[i].propertyTwo) 
      </div> 
      <div class="editor-field"> 
       @Html.TextBoxFor(m => m.items[i].propertyTwo) 
       @Html.ValidationMessageFor(m => m.items[i].propertyTwo) 
      </div> 
     </div> 
     <div class="edititem"> 
      <div class="editor-label"> 
       @Html.LabelFor(m => m.items[i].propertyThree) 
      </div> 
      <div class="editor-field"> 
       @Html.TextBoxFor(m => m.items[i].propertyThree) 
       @Html.ValidationMessageFor(m => m.items[i].propertyThree) 
      </div> 
     </div> 
    </div> 
} 

Oczywiście, aby mieć dostęp do indeksatora kolekcji to zakłada, że ​​nieruchomość items jest zadeklarowana jako albo List<SomeItem> lub SomeItem[]. Jeśli jest to IEnumerable<SomeItem>, to nie zadziała. Po prostu zmień typ tej właściwości na swoim modelu widoku.

+0

hmm Myślę, że moje jest IEnumerable, ponieważ używam obiektu podmiotu przekazanego prosto do widoku i wierzę, że oczekuje on IEnumerable. Zasadniczo muszę utworzyć obiekt typu viewview, jest to niepożądane, ponieważ w moim obiekcie znajduje się około 180 pól (nie ma wyboru w zmniejszaniu go, ponieważ nie jest to mój projekt lol). – DMCApps

+2

Masz 180 pól w formularzu i wszystkie są wymagane przez widok? W takim przypadku użycie modelu widoku nie przyniesie istotnych korzyści. W takim przypadku możesz użyć niestandardowego szablonu edytora. Nie pisz w widoku żadnych pętli 'for'. Po prostu zamień całą pętlę na '@ Html.EditorFor (x => x.items)', a następnie zdefiniuj niestandardowy szablon edytora dla klasy 'SomeItem' -' ~/Views/Shared/EditorTemplates/SomeItem.cshtml'. ASP.NET MVC automatycznie wywoła ten szablon niestandardowy dla każdego elementu z kolekcji elementów, więc szablon będzie silnie wpisany do '@model SomeItem' –

+1

Następnie wewnątrz niestandardowego szablonu wstaw znacznik z elementami div i użyj następujących wyrażeń:' @ Html.TextBoxFor (x => x.propertyOne), ... '. W takim przypadku helper wygeneruje odpowiednie nazwy dla pól wejściowych. –

Powiązane problemy