2010-03-17 10 views
9

je les types et les classes suivantes:modèle de liaison avec des modèles enfants imbriqués et PartialViews dans ASP.NET MVC

namespace MVC.Models 

public class Page 
{ 
    public EditableContent Content {get; set; } 
} 

public class EditableContent 
{ 
    public TemplateSection SidebarLeft {get; set; } 
    public TemplateSection SidebarRight {get; set; } 
} 

Je veux modifier l'instance Page dans mon Edit.aspx View. Parce que EditableContent est également attaché à d'autres modèles, j'ai un PartialView appelé ContentEditor.ascx qui est fortement typé et prend une instance de EditableContent et le rend.

La partie de rendu fonctionne très bien, mais quand je publie - tout ce qui est à l'intérieur de mon n'est pas lié - ce qui signifie que Page.Content est null.

Sur le PartialView, j'utilise fortement typé Html Helpers pour ce faire:

<%= Html.HiddenFor(m => m.TemplateId) %> 

Mais parce que les éléments d'entrée sur la forme qui sont rendus par ContentEditor.ascx ne soit pas le préfixe Content à son attribut id - la les valeurs ne sont pas liées à Page.

J'ai essayé d'utiliser des aides faiblement typé pour surmonter ceci:

<%= Html.Hidden("Content.TemplateId", Model.TemplateId) %> 

Et quand je fais face à une propriété qui est un List<T> de quelque chose il est très laid. Je dois ensuite rendre les index de collection manuellement.

Dois-je mettre à la fois la page et EditableContent en tant que paramètres à l'action du contrôleur ?:

public ActionResult Edit(Page page, EditableContent content) { ... } 

Qu'est-ce que je manque?

Répondre

18

Je vous suggère d'utiliser l'aide EditorFor

Modèle:

public class EditableContent 
{ 
    public string SidebarLeft { get; set; } 
    public string SidebarRight { get; set; } 
} 

public class Page 
{ 
    public EditableContent Content { get; set; } 
} 

Vues/Accueil/Index.aspx:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ToDD.Models.Page>" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 
    Home Page 
</asp:Content> 

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 
<% using (Html.BeginForm()) { %> 
    <%-- 
    This is the important part: It will look for 
    Views/Shared/EditorTemplates/EditableContent.ascx 
    and render it. You could also specify a prefix 
    --%> 
    <%= Html.EditorFor(page => page.Content, "Content") %> 
    <input type="submit" value="create" /> 
<% } %> 
</asp:Content> 

Vues/Shared/EditorTemplates/EditableContent.ascx :

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ToDD.Models.EditableContent>" %> 

<%= Html.TextBoxFor(m => m.SidebarLeft) %> 
<br/> 
<%= Html.TextBoxFor(m => m.SidebarRight) %> 

Et enfin Controller/HomeController:

public class HomeController : Controller 
{ 
    public ActionResult Edit() 
    { 
     var page = new Page 
     { 
      Content = new EditableContent 
      { 
       SidebarLeft = "left", 
       SidebarRight = "right" 
      } 
     }; 
     return View(page); 
    } 

    [HttpPost] 
    public ActionResult Edit(Page page) 
    { 
     return View(page); 
    } 
} 
+1

Cela fonctionne, mec! Merci. Je suppose que le EditorFor prend soin de tous les échafaudages pour lier tout ensemble. – MartinHN

+1

J'ai fait cela sur un de mes projets, mais pouvez-vous expliquer pourquoi 'Html.RenderPartial (" _blah ", Model.Blah)' ne fonctionne pas Darin? Comme c'est ce que nous avions précédemment. – GONeale

+7

@GONeale, cela ne fonctionne pas parce que vous passez Model.Blah, donc à l'intérieur du partiel vous êtes dans le contexte de Blah, pas dans le contexte de Model => tous les helpers que vous utilisez dans ce partiel génèrent des noms faux. Les modèles d'éditeur sont différents => ils prennent en compte le contexte parent et génèrent des aides qui sont utilisées à l'intérieur de ceux-ci pour générer des noms d'entrée appropriés. Regardez simplement votre balisage et vous verrez immédiatement la différence. Pour que le classeur par défaut fonctionne, vous devez respecter les conventions. –