2013-07-12 10 views
5

Ich habe eine Klasse namens CategoryModel, eine der Eigenschaften davon ist eine Liste von Objekten des gleichen Typs. So ist CategoryModel.Categories vom Typ List<CategoryModel>.MVC EditorFür Modellbindung für mehrere Bearbeitungsformulare auf einer Seite

Auf der Kategorieindexseite zeige ich für jede Kategorie einen Editor an, so dass der Benutzer einen beliebigen Kategoriennamen ändern kann, ohne dazu auf eine dafür bestimmte Seite wechseln zu müssen. Wie so:

<ul id="categories> 
    @Html.EditorFor(model => model.Categories) 
</ul> 

und der Editor-Vorlage für CategoryModel sieht wie folgt aus:

<li class="folder"> 
    @using (Html.BeginForm("Edit", "Category", new { id = Model.Key }, FormMethod.Post, new { @class = "ajaxoff"})) { 
     @Html.ValidationSummary(true) 
     @Html.HiddenFor(model => model.Key) 
     @Html.HiddenFor(model => model.ParentKey) 
     @Html.HiddenFor(model => model.Sequence) 
     @Html.HiddenFor(model => model.IncludeDeleted) 

     @Html.TextBoxFor(model => model.Name, null, new { @class = "catName" }) 
     @Html.ValidationMessageFor(model => model.Name) 

     <input type="submit" value="Save" class="icon save" /> 
    } 
</li> 

Das Problem, das ich habe ist, dass das Formular abschicken nicht richtig binden an die Edit Wirkung des CategoryController:

Wenn ich die Namen in den ausgeblendeten Feldern und Textfeldern überprüfe, werden sie entsprechend ihrer Position im aktuellen Kategorie kategorisiert ory (z.B. Categories[0].Name). Wenn ich jedoch eine dedizierte Bearbeitungsansicht erstelle, werden sie einfach entsprechend dem Feldnamen benannt (z. B. Name).

habe ich versucht, die Änderung der Controller eine Liste der Kategorien zu akzeptieren:

[HttpPost] 
public ActionResult Edit(List<CategoryModel> categories) 
{ 
    var category = categories.First(); 
} 

Dies funktioniert, wenn ich die erste Kategorie, aber keiner der anderen (in den Fällen, Categories ist null) einreichen.

ich auch versucht haben, zu verändern, wie ich meine EditorFor angezeigt werden, indem Sie diese:

<ul id="categories> 
    @foreach (var cat in Model.Categories) 
    { 
     @Html.EditorFor(model => cat); 
    } 
</ul> 

, die die Feldnamen ändert sich das gleiche für jede Kategorie sein (zB alle Kategorienamen sind cat.Name genannt), die ich Glaube ist ein Schritt in die richtige Richtung.

Also wie binde ich korrekt an meinen Controller? Mir ist klar, dass ich die gesamte Elternkategorie einreichen und dann jede Unterkategorie speichern kann, aber das scheint eine sehr ineffiziente Art zu sein, eine einzelne Änderung einzureichen.

Antwort

6

ich entdeckt, wie dies zu tun. Es gibt eine Überlastung für Html.EditorFor, dass Sie die htmlFieldName Eigenschaft (der dritte Parameter im Beispiel unten) angeben kann:

@foreach (var cat in Model.Categories) 
{ 
    @Html.EditorFor(model => cat, null, ""); 
} 

Diese alle Feldnamen machen ohne Präfix und ermöglicht es mir, jede einzelne Kategorie erfolgreich einreichen .

+1

Ich habe das gemacht, aber ich bekomme immer noch [0] und [1] nach den Feldnamen, wie bist du damit umgegangen? – Dennis

+1

Ich habe das von Ihnen beschriebene Problem nicht bekommen. Wenn Sie @ Html.EditorFor (model => model.Categories, null, "") anstelle der obigen Schleife verwenden, erhalten Sie [0] und [1] vor den Feldnamen, da Sie ein Array an übergeben die Methode EditorFor anstelle eines individuellen Modells. – Maloric

0

Ihre Bearbeitungsaktion akzeptiert die CategoryModel-Kategorie. Daher müssen Sie das Modellpräfix für die rechte Bindung zurücksetzen. Dazu müssen Sie Ihre eigene Erweiterungsmethode für Htmlhelper wie diese erstellen:

public class BeginHtmlScope : IDisposable 
    { 
     private readonly TemplateInfo templateInfo; 
     private readonly string previousHtmlFieldPrefix; 

     public BeginHtmlScope(TemplateInfo templateInfo, string htmlFieldPrefix) 
     { 
      this.templateInfo = templateInfo; 

      previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix; 
      templateInfo.HtmlFieldPrefix = htmlFieldPrefix; 
     } 

     public void Dispose() 
     { 
      templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix; 

     } 
    } 
    public static class MyHtmlExtensions 
    { 
     public static IDisposable BeginHtmlScope(this HtmlHelper html, string htmlFieldPrefix) 
     { 
      return new BeginHtmlScope(html.ViewData.TemplateInfo, htmlFieldPrefix); 
     } 
    } 

Und dann in Ihrem Editor Vorlage verwenden es:

@using (Html.BeginHtmlScope("")) 
{ 
    <li class="folder"> 
    @using (Html.BeginForm("Edit", "Category", new { id = Model.Key }, FormMethod.Post, new { @class = "ajaxoff"})) { 
     @Html.ValidationSummary(true) 
     @Html.HiddenFor(model => model.Key) 
     @Html.HiddenFor(model => model.ParentKey) 
     @Html.HiddenFor(model => model.Sequence) 
     @Html.HiddenFor(model => model.IncludeDeleted) 

     @Html.TextBoxFor(model => model.Name, null, new { @class = "catName" }) 
     @Html.ValidationMessageFor(model => model.Name) 

     <input type="submit" value="Save" class="icon save" /> 
    } 
</li> 

} 
+0

Leider hat dies das gleiche Problem wie die foreach-Schleife - die Feldnamen sind Kategorien [0] .Name, Kategorien [1] .Name usw., und das CategoryModel bindet nicht an die Aktion Bearbeiten. – Maloric

+0

Es tut mir leid, dass Sie Ihre Frage falsch verstanden haben. Ich habe meine Antwort bearbeitet. –