2016-04-11 1 views
3

Wenn das Modell eine Liste von Objekten ist, dann erstellt @Html.LabelFor model => model[i].member) ein leeres for Attribut. Der DisplayName funktioniert ordnungsgemäß, Modellbindung funktioniert auch einwandfrei. Das einzige, was nicht funktioniert, ist das for Attribut.Razor: Wenn das Modell List <> ist, dann erzeugt @ Html.LabelFor ein leeres "for" -Feld

Im Folgenden finden Sie zwei Versionen des MVC-Codes. Die ersten drei Codefragmente sind für die Kombination aus Modell, Controller und Ansicht, die nicht funktioniert (das Modell ist eine Liste). Der zweite Satz von 3 Code-Snippets funktioniert. Diesmal ist die Liste in ein Objekt eingeschlossen.

Was fehlt mir?

Modell:

public class ViewModel { 
    public bool ClickMe { get; set; } 
} 

Controller:

public ActionResult LabelForViewModel() { 
    List<ViewModel> model = new List<ViewModel>() { 
     new ViewModel() { ClickMe = true} 
    }; 
    return View(model); 
} 

Ausblick:

@model List<ModelBinding.Models.ViewModel> 
// form code removed for brevity 
@for (var i = 0; i < Model.Count; i++) { 
    <div class="form-group"> 
     @Html.LabelFor(model => model[i].ClickMe) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model[i].ClickMe, new { htmlAttributes = new { @class = "form-control" } }) 
      @Html.ValidationMessageFor(model => model[i].ClickMe, "", new { @class = "text-danger" }) 
     </div> 
    </div> 
} 

Markup:

<div class="form-group"> 
    <label for="">ClickMe</label> 
    <div class="col-md-10"> 
     <input name="[0].ClickMe" class="form-control check-box" type="checkbox" checked="checked" value="true" data-val-required="The ClickMe field is required." data-val="true"><input name="[0].ClickMe" type="hidden" value="false"> 
     <span class="field-validation-valid text-danger" data-valmsg-replace="true" data-valmsg-for="[0].ClickMe"></span> 
    </div> 
</div> 

Bitte beachten Sie, dass das for-Feld leer ist und die Eingabe kein ID-Feld hat (das wird im "for" -Feld verwendet).

Ich habe ein Wrapper-Modell, das eine Liste von Objekten enthält, den Controller und die Ansicht geändert und dann funktioniert es gut. In diesem Fall ist das Feld "for" korrekt ausgefüllt und alles funktioniert wie erwartet.

public class ListWrapper { 
    public List<ViewModel> ViewModels { get; set; } 
} 

Ausblick:

@for (var i = 0; i < Model.ViewModels.Count; i++) { 
    <div class="form-group"> 
     @Html.LabelFor(model => model.ViewModels[i].ClickMe) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.ViewModels[i].ClickMe, new { htmlAttributes = new { @class = "form-control" } }) 
      @Html.ValidationMessageFor(model => model.ViewModels[i].ClickMe, "", new { @class = "text-danger" }) 
     </div> 
    </div> 
} 

Markup:

<div class="form-group"> 
    <label for="ViewModels_0__ClickMe">ClickMe</label> 
    <div class="col-md-10"> 
     <input name="ViewModels[0].ClickMe" class="form-control check-box" id="ViewModels_0__ClickMe" type="checkbox" checked="checked" value="true" data-val-required="The ClickMe field is required." data-val="true"><input name="ViewModels[0].ClickMe" type="hidden" value="false"> 
     <span class="field-validation-valid text-danger" data-valmsg-replace="true" data-valmsg-for="ViewModels[0].ClickMe"></span> 
    </div> 
</div> 

So scheint es, dass das for Attribut leer ist nur, wenn das Modell eine Liste von Objekten ist.

Ist dies ein bekanntes Problem? Oder vielleicht vermisse ich etwas?

Antwort

2

Dieses Verhalten ist das Ergebnis des Frameworks, das den HTML-4-Spezifikationen entspricht. In HTML-4

ID und NAME-Token müssen mit einem Buchstaben ([A-Za-z]) beginnen und können durch eine beliebige Anzahl von Buchstaben, Ziffern ([0-9]), Bindestrichen (“folgen - "), Unterstriche (" _ "), Doppelpunkte (": ") und Punkte (". ").

Wenn Ihr Modell eine Sammlung ist und Sie @Html.EditorFor(m => m[i].SomeProperty) Formular-Steuerelemente zu erzeugen, wobei das Verfahren name und id Attribute erzeugt auf den Namen der Eigenschaft basiert. In diesem Fall wird das name Attribut für das erste Element in der Sammlung

name="[0].SomeProperty" 

aber mit jQuery Selektoren zu vermeiden Konflikte sein wird, ersetzt das Verfahren ., [ und ] Zeichen mit einem Unterstrich _ wenn das id Attribut zu erzeugen, die würde in

id="_0__SomeProperty" 

sondern weil dies die HTML-4-Spezifikation gemäß ungültig ist, tut der Helfer nicht ausgegeben es in dem HTML-Code.

Das gleiche gilt, wenn @Html.LabelFor() verwendet (weil die zugeordnete Form-Steuer wird keine id Attribute hat, wird der Wert des for Attributs wird nicht ausgegeben in dem HTML-Format.

anzumerken, dass in HTML-5, das id Attribute wäre gültig, so hoffentlich wird dieses Verhalten in der Zukunft fallen gelassen werden

Ihr zweites Beispiel funktioniert, weil id="ViewModels_0__ClickMe "mit einem Buchstaben beginnt und daher gültig ist

Randbemerkung:.. Sie lösen könnten die erste Ausgabe mit dem eigenen id Attribute zu erzeugen, zum Beispiel

@Html.LabelFor(model => model[i].ClickMe, new { for = string.Format("item{0}", i) }) 
@Html.EditorFor(model => model.ViewModels[i].ClickMe, new { htmlAttributes = new { @class = "form-control", id = string.Format("item{0}", i) } }) 
+0

@GabrielLuci, das Modell keine Eigenschaft enthält namens 'Item' so würde dies nicht funktionieren und könnte binden nie –

+0

zu etwas Ja, ich merke, dass jetzt . [MSDN] (https://msdn.microsoft.com/en-us/library/0ebtbkkc (v = vs.110) .aspx? Cs-save-lang = 1 & cs-lang = csharp) beschreibt eine Eigenschaft 'Item', aber es wird nur über den Indexer verfügbar gemacht. –

+0

Mit Linq konnte er 'Model.ElementAt [i] .ClickMe' verwenden. Das würde wahrscheinlich eine ID wie "ElementAt_0__ClickMe" erzeugen, vielleicht? Linq ist hier wahrscheinlich nicht ideal. –

0

Die @ model-Deklaration weist das Modellobjekt der Variablen Model zu (beachten Sie das Captial 'M'). Aber dann liest du aus model, die nicht zugewiesen wurde.

Try this:

@model List<ModelBinding.Models.ViewModel> 
    // form code removed for brevity 
     @for (var i = 0; i < Model.Count; i++) { 
      <div class="form-group"> 
       @Html.LabelFor(model => Model[i].ClickMe) 
       <div class="col-md-10"> 
        @Html.EditorFor(model => Model[i].ClickMe, new { htmlAttributes = new { @class = "form-control" } }) 
        @Html.ValidationMessageFor(model => Model[i].ClickMe, "", new { @class = "text-danger" }) 
       </div> 
      </div> 
     } 

das erklärt nicht, warum Ihr zweites Beispiel überhaupt funktioniert, aber hey, geben diesem einen Versuch.

Verwandte Themen