2013-02-11 11 views
54

Wenn ich einen Satz von Eingaben in einer Form 4 zu einem List in MVC binden will, weiß ich, dass die folgende Namenskonvention für inputname Attribute funktionieren:Wie funktioniert MVC 4 List Model Binding?

<input name="[0].Id" type="text" /> 
<input name="[1].Id" type="text" /> 
<input name="[2].Id" type="text" /> 

Aber ich bin gespannt, wie nachsichtig die Modellbinder ist. Was ist zum Beispiel mit:

<input name="[0].Id" type="text" /> 
<input name="[3].Id" type="text" /> 
<input name="[8].Id" type="text" /> 

Wie würde der Modellbinder damit umgehen? Würde es sich an eine List der Länge 9 mit Nullen binden? Oder würde es immer noch an eine List der Länge 3 binden? Oder würde es überhaupt ersticken?

Warum ist mir egal

ich eine dynamische Form implementieren möchten, in dem der Benutzer Zeilen zum Formular hinzufügen können, und auch Zeilen aus dem Formular löschen. Wenn also ein Benutzer Zeile 2 von 8 Zeilen löscht, möchte ich wissen, ob ich alle nachfolgenden Eingaben neu nummerieren muss.

+1

einen Blick auf diese: http://stackoverflow.com/questions/ 7807127/Nicht-sequenzielle-Liste-Bindung-nicht-arbeiten. Die Frage zeigt eine Syntax für nicht-sequenzielle Bindung (und die Antwort bestätigt ihre Verfügbarkeit in MVC2 und höher). Ich habe es gelegentlich benutzt. Zu Ihrer ursprünglichen Frage: Wenn ich mich richtig erinnere, wird es scheitern ... aber es ist einfach genug, es zu versuchen, bevor Sie sich mit manueller indizierter, nicht sequentieller Bindung beschäftigen. –

+1

@TimMedora, Danke - Nicht-sequenzielle Bindung war eine hilfreiche Terminologie, die mir fehlte. – Eric

+4

Das Thema ist überraschend obskur. Wenn Sie nach etwas suchen, gibt es ein paar gute Blogs zu diesem Thema, und dieses Buch behandelt es gut in einem der späteren Kapitel: http://www.amazon.com/Pro-ASP-NET-MVC-3-Framework/dp/1430234040 –

Antwort

45

Es gibt ein bestimmtes Draht-Format für die Verwendung mit Sammlungen. Dies wird auf Scott Hanselman Blog diskutiert hier:

http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx

Ein weiterer Blog-Eintrag von Phil Haack spricht über dies hier:

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Schließlich ist ein Blog-Eintrag, das tut genau das, was Sie hier wollen :

http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/

+0

Perfekt, danke – Eric

+4

@shashwat - wie gibt man eine klare Ja oder Nein Antwort auf offene Fragen, in denen die Antwort möglicherweise nicht ja oder nein sein kann? –

+1

@AnimalsAreNotOursToEat 'Wie funktioniert MVC 4 List Model Binding?' ** Ja ** – Jonesopolis

3

Ich habe dynamische Liste, die wie folgt aussieht:

<ul id="okvedList" class="unstyled span8 editableList"> 
<li> 
    <input data-val="true" data-val-required="The Guid field is required." id="Okveds_0__Guid" name="Okveds[0].Guid" type="hidden" value="2627d99a-1fcd-438e-8109-5705dd0ac7bb"> 
    --//-- 
</li> 

so, wenn ich hinzufügen oder die Zeile (li-Element) lösche ich Elemente neu anordnen müssen

this.reorderItems = function() { 
     var li = this.el_list.find('li'); 

     for (var i = 0; i < li.length; i++) { 
      var inputs = $(li[i]).find('input'); 

      $.each(inputs, function() { 
       var input = $(this); 

       var name = input.attr('name'); 
       input.attr('name', name.replace(new RegExp("\\[.*\\]", 'gi'), '[' + i + ']')); 

       var id = input.attr('id'); 
       input.attr('id', id.replace(new RegExp('_.*__', 'i'), '_' + i + '__')); 
      }); 
     } 
    }; 

diese Liste platziert in einfache Html.BeginFrom von clientside und like Liste in action parameter auf serverside

1

Ich habe auch ein ähnliches Problem in der Vergangenheit, und ich benutze KnockoutJS, um ein solches Szenario zu behandeln.

Grundsätzlich senden Knockout die Sammlung in einer JSON-Zeichenfolge, und ich deserialisierte sie in meinem Controller.

Für weitere Informationen: http://learn.knockoutjs.com/#/?tutorial=collections

15

folgte ich diesen ein pproach in den obigen Blogs verlinkt und ein paar Details hinzugefügt, die für einige hilfreich sein könnten - vor allem, weil ich eine beliebige Anzahl von Zeilen dynamisch hinzufügen wollte, aber AJAX dazu nicht verwenden wollte (ich wollte, dass das Formular nur im Post einreicht)). Ich wollte mir auch keine Gedanken über die Aufrechterhaltung sequentieller IDs machen.Ich war eine Liste von Start- und Enddaten Erfassung:

Ansicht Modell:

public class WhenViewModel : BaseViewModel { 
    public List<DateViewModel> Dates { get; set; } 
    //... Other properties 
} 

Start/End Date Ansicht Modell:

public class DateViewModel { 
    public string DateID { get; set; } 
    public DateTime? StartDate { get; set; } 
    public DateTime? EndDate { get; set; } 
} 

Dann sie auf der Seite mit (mit Datumspicker):

<div class="grid-8-12 clear" id="DatesBlock"> 
@{ 
    foreach (DateViewModel d in Model.Dates) { 
     @:<div class="grid-5-12 left clear"> 
      @Html.Hidden("Dates.Index", d.DateID) 
      @Html.Hidden("Dates[" + d.DateID + "].DateID", d.DateID) //ID again to populate the view model 
      @Html.TextBox("Dates[" + d.DateID + "].StartDate", 
          d.StartDate.Value.ToString("yyyy-MM-dd")) 
     @:</div> 
     @:<div class="grid-5-12"> 
      @Html.TextBox("Dates[" + d.DateID + "].EndDate", 
          d.EndDate.Value.ToString("yyyy-MM-dd")) 
     @:</div> 

     <script type="text/javascript"> 
      $('input[name="Dates[@d.DateID].StartDate"]') 
       .datepicker({ dateFormat: 'yy-mm-dd'}); 
      $('input[name="Dates[@d.DateID].EndDate"]') 
       .datepicker({dateFormat: 'yy-mm-dd'}); 
     </script> 
    } 
} 
</div> 
<a href="#" onclick="AddDatesRow()">Add Dates</a> 

Wie der Blogpost, der im oben beschriebenen @ErikTheVikings-Post verlinkt ist, wird die Sammlung durch das wiederholte verdeckte Element @Html.Hidden("Dates.Index", d.DateID) für jeden Eintrag in der Sammlung auf der Seite erstellt.

Ich wollte Reihen beliebig hinzufügen, ohne AJAX unter Verwendung von Daten zurück an den Server zu schreiben, die ich eine Vorlage von einer „Reihe“/Stück in der Sammlung eine versteckte div tat, indem enthält:

Versteckt „Vorlage "row:

<div id="RowTemplate" style="display: none"> 
    <div class="grid-5-12 clear"> 
     @Html.Hidden("Dates.Index", "REPLACE_ID") 
     @Html.Hidden("Dates[REPLACE_ID].DateID", "REPLACE_ID") 
     @Html.TextBox("Dates[REPLACE_ID].StartDate", "") 
    </div> 
    <div class="grid-5-12"> 
     @Html.TextBox("Dates[REPLACE_ID].EndDate", "") 
    </div> 
</div> 

dann verwendet jQuery, die die Vorlage Klone stellt eine Zufalls-ID für eine neue Zeile zu verwenden und fügt die nun sichtbar geklont Reihe zum enthält div oben:

jQuery um den Vorgang abzuschließen:

<script type="text/javascript"> 
    function AddDatesRow() { 
     var tempIndex = Math.random().toString(36).substr(2, 5); 
     var template = $('#RowTemplate'); 
     var insertRow = template.clone(false); 
     insertRow.find('input').each(function(){ //Run replace on each input 
      this.id = this.id.replace('REPLACE_ID', tempIndex); 
      this.name = this.name.replace('REPLACE_ID', tempIndex); 
      this.value = this.value.replace('REPLACE_ID', tempIndex); 
     }); 
     insertRow.show(); 
     $('#DatesBlock').append(insertRow.contents()); 

     //Attach datepicker to new elements 
     $('input[name="Dates['+tempIndex+'].StartDate"]') 
      .datepicker({dateFormat: 'yy-mm-dd' }); 
     $('input[name="Dates['+tempIndex+'].EndDate"]') 
      .datepicker({dateFormat: 'yy-mm-dd' }); 
    } 
</script> 

JSFiddle Beispiel für das Ergebnis: http://jsfiddle.net/mdares/7JZh4/

0

ich kleines Problem, wenn ich Chrome-Browser und klicken Sie auf die Zurück-Taste, und ich finde die Eingabe mit Typ = "Versteckt", wenn dynamisch eingestellte Werte nicht korrekt vom Chrome Browser gehandhabt wurden.

vielleicht können wir

<input type="hidden" name="Detes.Index" value="2016/01/06" /> 

zu

<div style="display: none"> 
    <input type="text" name="Detes.Index" value="2016/01/06" /> 
</div> 

Formular weitere Informationen ändern: Chrome doesn't cache hidden form field values for use in browser history http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/