2013-12-19 16 views
8

Ich habe View-Modell, das ein anderes Kindmodell hat, um die Teilansicht (unten) zu rendern.MVC4 - Teilansicht Modellbindung während Submit

public class ExamResultsFormViewModel 
{ 
    public PreliminaryInformationViewModel PreliminaryInformation { get; set; } 

    public string MemberID { get; set; } 

    public string MemberName { get; set; } 

    public int PatientID { get; set; } 

    public string ConfirmationID { get; set; } 

    public bool IsEditable { get; set; } 

    #region Select Lists 
    public SelectList ProviderOptions { get; set; } 
    #endregion 
} 

public class PreliminaryInformationViewModel 
{ 
    public string ProviderName { get; set; } 

    public string ProviderID { get; set; } 

    public string ServiceLocation { get; set; } 
} 

Dieses PreliminaryInformationViewModel View-Modell als Kind Modelle in einem anderen Ansicht Modell auch auf verschiedenen Seiten aktualisiert kann, da diese vorläufige Informationen verwendet werden.

Also habe ich diese vorläufige Informationen als separate Teil erstellt und auf anderen Seiten enthalten.

@{Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);} 

Innerhalb des Teils

@model Web.Models.Preliminary.PreliminaryInformationViewModel 
<div> 
    @Html.TextBoxFor(x => x.DateOfService }) 
</div> 

Aber das Problem während sie dieses vorläufigen Modell vorlegen ist immer null aus dem Grunde Attribut HTML Namen immer als

gemacht wird, aber wenn ich pass das Elternmodell zum Teil wie unten.

@model Web.Models.Exam.ExamResultsFormViewModel 
<div> 
    @Html.TextBoxFor(x => x.PreliminaryInformation.DateOfService }) 
</div> 

nun das HTML-Element erzeugt als

<input type = 'text' name='PreliminaryInformation.DateOfService.DateOfService' id='PreliminaryInformation.DateOfService'> 

und bindet es richtig während der einreichen.

Ich verstehe, dass MVC den Wert des Elements basierend auf dem Wert des Namensattributs bindet, aber die zweite Implementierung würde mich brauchen, um eine mehrfache partielle für jede Seite zu erstellen, die ich nicht mag.

Bis jetzt konnte ich keine Lösung finden, um mit der ersten Implementierung zu arbeiten, gibt es so, wie ich vorläufigen Informationsmodell Wert binden kann, während mit der ersten Implementierung zu übermitteln.

Antwort

6

Sie müssen eine Editorvorlage für PreliminaryInformationViewModel erstellen, um die Teilansicht zu ersetzen, und dann mit Html.EditorFor(m => m.PreliminaryInformation) aufrufen. Referenz this solution. Das Erstellen der Vorlage sollte so einfach sein wie das Verschieben der Teilansicht in das Verzeichnis Views/Shared/EditorTemplates. Html.EditorFor(...) wird diese automatisch Vorlage nach Art basierend verwenden Sie als Modell vorbei sind (in diesem Fall PreliminaryInformationViewModel)

+0

Okay mit EditerFor löst das Bindungsproblem, aber es ersetzt auch alle Klassen und Styling, die ich in der Ansicht angewendet habe. ' ' – Sathish

+0

verschieben Sie Ihre Teilansicht zu Views \ Shared \ EditorTemplates, der Aufruf zu 'Html.EditorFor (.. .) 'sollte automatisch diese Ansicht für Ihre Editor-Vorlage basierend auf dem Typ auswählen, den Sie als Modell übergeben – Moho

+0

Danke für die Antwort Moho. Ich war in der Lage, partiell und Elemente Wert binden sind während des Einreichen mit EditorFor, aber Rendern mit EditorFor fügt einige Editor-Klassen Divs und Elemente und entfernt diejenigen, die tatsächlich auf der Ansicht platziert wurde Gibt es eine Möglichkeit, die wir verhindern können Hinzufügen dieser Editor-Klassen zu den Elementen im Teil. – Sathish

0

Quick Tip: Wenn Ihr EditorFor Methode aufrufen, können Sie den Namen der Vorlage als Parameter eingestellt die Html.EditorFor-Methode. Alternativ können Namenskonventionen Ihr Freund sein. Stellen Sie nur sicher, dass der Name der Editiervorlage genau dem Namen des Modelleigenschaftstyps

entspricht, d. h. Modelleigenschaftentyp 'CustomerViewModel' => 'CustomerViewModel.cshtml' Editorvorlage.

3

Ich lief auch in dieses Problem. Ich werde meine Lösung mit Ihrem Code erklären. Ich begann damit:

@{ 
    Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation); 
} 

Die Aktion, die dem HTTP-Post entspricht, suchte nach dem übergeordneten Modell. Der HTTP-Post übermittelte das Formular korrekt, aber es gab keinen Verweis in dem Kind, das sich teilweise auf das Elternteil bezieht. Die übergebenen Werte aus dem Child-Partial wurden ignoriert und die entsprechende Child-Eigenschaft blieb null.

Ich habe eine Schnittstelle, IPreliminaryInfoCapable, der eine Definition für das Kind Typ enthalten, etwa so:

public interface IPreliminaryInfoCapable 
{ 
    PreliminaryInformationViewModel PreliminaryInformation { get; set; } 
} 

ich meine Eltern Modell diese Schnittstelle implementieren gemacht. Meine Teilansicht verwendet dann die Schnittstelle an der Spitze als Modell:

@model IPreliminaryInfoCapable 

Schließlich kann meine Eltern Ansicht den folgenden Code verwenden sich teilweise um das Kind zu übergeben:

@{ 
    Html.RenderPartial("ChildPartial", Model); 
} 

Dann wird das Kind Teil kann das Kind-Objekt verwenden, etwa so:

@model IPreliminaryInfoCapable 
... 
@Html.LabelFor(m => m.PreliminaryInformation.ProviderName) 
etc. 

All dies füllt richtig das übergeordnete Modell auf http Post an die entsprechende Aktion.

0

Bitte nehmen Sie die untenstehenden Änderungen an Ihrer Teilseite vor. so wird es kommen mit Ihren Eltern Modell

//Parent Page 
@{Html.RenderPartial("_PreliminaryInformation", Model.PreliminaryInformation);} 

//Partial Page 
@model Web.Models.Preliminary.PreliminaryInformationViewModel 
@using (Html.BeginCollectionItem("PreliminaryInformation", item.RowId, true)) 
    { 
<div> 
@Html.TextBoxFor(x => x.DateOfService }) 
</div> 

} 
23

ich seine weiß ein bisschen spät, aber es könnte

jemand helfen Wenn Sie komplexes Modell haben, können Sie es immer noch in Teil passieren mit:

@Html.Partial("_YourPartialName", Model.Contact, new ViewDataDictionary() 
{ 
    TemplateInfo = new TemplateInfo() 
    { 
     HtmlFieldPrefix = "Contact" 
    } 
}) 

wo ich Modell mit Eigenschaft "Kontakt" definiert habe. Nun, was HtmlFieldPrefix tut, ist die Eigenschaft hinzufügen, für jedes Modell verbindlich „so das Modell Bindemittel das übergeordnete Modell finden kann“

Es gibt eine Blog-Post über sie: http://www.cpodesign.com/blog/bind-partial-view-model-binding-during-submit/

.NET Core 2 Bindung

In .NET Core 2 und MVC funktioniert die obige Antwort nicht, die Eigenschaft ist nicht mehr einstellbar.

Wie auch immer die Lösung ist sehr ähnlich.

@ {Html.ViewData.TemplateInfo.HtmlFieldPrefix = "Kontakt"; } @await Html.PartialAsync ("_YourPartialName", Model.Contact)

nachdem Sie Ihr Modell senden können, wird es erneut binden.

Hoffnung, die

+0

Was passiert, wenn ich eine Liste von Kontaktobjekten habe und diese an das Modell binden möchte? – user3281466

+0

Sie müssen für jede Schleife mit dem Stil über – cpoDesign

+0

wickeln Ich sehe keinen vernünftigen Ort, wo die Schleife gehen soll, könnten Sie bitte beraten? – user3281466

2

Sie hilft die HtmlFieldPrefix an der Spitze Ihrer Teilansicht hinzu:

@{ 
    ViewData.TemplateInfo.HtmlFieldPrefix = "Contact"; 
} 

Dies ist der gleiche Ansatz wie das von @cpoDesign beschrieben, aber es bedeutet, dass Sie das Präfix halten in Ihrer Teilansicht, wenn Sie das tun müssen.

+0

ja ich weiß, das könnte ein Kommentar zu der ursprünglichen Antwort sein, aber ich habe nicht die rep. – Chaholl