2013-05-27 2 views
1

BUT:Imbrication illimitée sur MVC4

ont une hiérarchie d'éléments imbriqués avec la profondeur illimitée.

PROBLÈME:

J'ai une classe A, qui comprend une instance d'une classe B.

classe B a une liste d'objets de commentaires. Chaque commentaire peut avoir une liste de commentaires "enfant". Par conséquent, nous avons une structure arborescente avec une imbrication à profondeur illimitée (par exemple A.B.Comments [1] .Commentaires [0] .Commentaires [5] ....).

classe A éditeur Voir appelle:

@Html.EditorFor(m=>m.B) 

classe B Modèle éditeur a (simplifié):

<table id="B-comments"> 
    @for (int i = 0; i < Model.Comment.ToList().Count(); i++) 
    { 
     @Html.EditorFor(m => m.Comment.ToList()[i]) 
    } 
</table> 
<a id="addCommentToB" href="#">Add Comment</a> 

Et chaque éditeur de modèle pour la classe Commentaire consiste en (simplifié):

<tr> 

    @using (Html.BeginCollectionItem("B.Comment")) 
    { 
     <td> 
      (... STUF ...)  
     </td> 

     (...STUF...) 

     <td> 
      <table class ="commentReplies"> 
      @for (int i = 0; i < Model.Comment1.ToList().Count(); i++) 
      { 
       @Html.EditorFor(m => m.Comment1.ToList()[i]) 
      } 
      </table> 
      <a id="addReply" href="#">Add Reply</a> 

    </td> 
} 

Les liens <a ...> sont utilisés pour obtenir des lignes d'entrée via Ajax et les ajouter aux tables correspondantes.

Lors de la soumission, la liaison fonctionne uniquement pour le premier niveau d'imbrication (A.B.Comments, mais pas pour les commentaires sur les objets dans A.B.Comments). La raison, est probablement due à la ligne @using (Html.BeginCollectionItem("B.Comment")), qui génère les index seulement pour 1 niveau de profondeur.

Je serais très reconnaissant si quelqu'un pouvait me donner une suggestion sur la façon d'autoriser l'imbrication illimitée étant donné ces circonstances. Est-il possible de modifier dynamiquement l'argument dans Html.BeginCollectionItem(ARG)?

Vive

EDIT: Les ViewModels simplifiées, comme l'a demandé

public partial class A 
{ 
    (...) 
    public int BID{ get; set; } 
    public virtual B B{ get; set; } 
    (...) 
} 

public partial class B 
{ 
    (...) 
    public virtual ICollection<Comment> Comment { get; set; } 
} 

public partial class Comment 
{ 
    (...) 
    public Nullable<int> ParentID { get; set; } 
    public virtual ICollection<Comment> Comment1 { get; set; } 
    public virtual Comment Comment2 { get; set; } 
    public virtual B B { get; set; } 
    public Nullable<int> BID { get; set; } 
} 

ADDENDA:

J'ai fini par créer un BeginCollectionItem() différent helper HTML qui ne continue pas d'ajouter des préfixes aux noms et aux ID du html généré.

.: par exemple

comme je l'avais, si j'avais un commentaire dans un commentaire, l'assistant Html générerait des balises comme ceci: name="*B.Comment[521cfe57-23aa-42d4-9b63-b7fcdd8799c3].*B.Comment.index" Ma nouvelle méthode génère juste name="Entity.Comment.index" qui permet la liaison de fonctionner correctement. Alberto León m'a donné le bon indice en me rappelant que je ne dois pas réellement faire une liaison en profondeur (par exemple, lier le commentaire d'un commentaire à son parent et ainsi de suite) comme capturant la relation entre le commentaire et les objets B suffisent pour que la reliure fonctionne comme je le souhaite.

+0

Pourriez-vous joindre au moins une version limitée du code source de votre modèle de vue? Merci. – Jakub

+0

Je ne pense pas vraiment que ce soit nécessaire pour ce problème, mais j'ai ajouté cela dans mon EDIT au cas où cela pourrait aider à mieux comprendre le problème. – user1987392

Répondre

1

Vous le faites de manière compliquée. Il y a quelques années, j'ai conçu le moteur social Bside qui est malheureusement mort parce qu'il n'y a pas de fondations.

J'ai trouvé le même problème et il a une solution très simple.

Vous devez attribuer un guid à chaque contenu et considérer chaque commentaire comme un nouveau contenu, afin que vous puissiez toujours rechercher le contenu du guid. Ensuite, il vous suffit de créer l'interface ICommentable avec la propriété Commentaires et méthodes Add, Delete, Edit

Ensuite, vous avez besoin de la classe A héritée ICommentable et vous devez écrire l'implémentation. La même chose pour B.

Ensuite, dans la couche de gestion, vous obtenez A et B de la base de données ou de votre chemin de stockage. Et recherchez dans la base de données les commentaires A et B Lorsque vous l'obtenez, vous devez rechercher les commentaires pour les commentaires. Ainsi, dans le stockage, les commentaires sont toujours des commentaires.

N'est pas sensé sur l'élément de contenu lié au commentaire.

À propos de l'interface utilisateur avec ajax, j'ai utilisé jQuery. Alors n'essayez pas de lier s'il vous plaît. Traitez chaque commentaire comme un objet indépendant. Chaque bouton d'ajout pour ajouter un commentaire, et enregistrer, ne peut être référence que le commentaire. Vous avez seulement besoin d'envoyer à la méthode MVC le formulaire avec le nouveau commentaire. Ne pas oublier le guid de l'élément de contenu parent (classe A, ou B ou tout objet Comment)

+0

J'ai fini par le faire d'une manière différente, mais vous m'avez indiqué dans la bonne direction et votre réponse pourrait être valable pour celui qui trébuche sur le même problème. Merci. – user1987392

0

Vous pouvez utiliser ViewData.TemplateInfo.GetFullHtmlFieldName() ou ViewData.TemplateInfo.HtmlFieldPrefix pour récupérer le chemin d'accès complet au modèle actuel