0

J'essaie d'appeler DisplayFor et DisplayForModel pour itérer un IEnumerable <> avec divers types d'éléments depuis une vue. J'ai des modèles définis pour chaque élément/type de modèle. Ce que je voudrais faire est de vérifier le ViewData.ModelMetadata.ContainerType à partir du Template afin que Template puisse déterminer s'il a été appelé dans le cadre d'une collection.ASP.NET MVC2: Pouvez-vous obtenir ModelMetadata.ContainerType à partir d'une collection?

Un exemple simple:

Index1.aspx: Pour rendre une collection de Foos.

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Foo>>" %> 
<asp:Content ContentPlaceHolderID="MainPlaceHolder" runat="server"> 
    <ul><%:Html.DisplayForModel()%></ul> 
</asp:Content> 

Index2.aspx: Pour rendre un Foo à partir de Bar.

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Bar>" %> 
<asp:Content ContentPlaceHolderID="MainPlaceHolder" runat="server"> 
    <%:Html.DisplayFor(m => m.Foo)%> 
</asp:Content> 

Shared \ DisplayTemplates \ Foo.ascx: Un modèle contextuel pour Foo.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Foo>" %> 
<% var tag = typeof(IEnumerable).IsAssignableFrom(ViewData.ModelMetaData.ContainerType) ? "li" : "div"; 
%> <<%:tag%>><%:Model.Name%></<%:tag%>> 

Le problème avec cet exemple est que ViewData.ModelMetaData.ContainerType est nulle dans le modèle quand résolu si Index1.aspx. De ce que j'ai lu sur Brad Wilson's post et d'autres il a à voir avec l'utilisation de IEnumerable et son être une interface.

Existe-t-il un moyen d'assurer que ContainerType est défini? Peut-être en créant un ModelMetadataProvider? J'ai regardé dans ce breifly, mais il semble que la valeur ContainerType est déterminée avant, puis transmise au fournisseur.

Toutes les suggestions seraient appréciées.

Répondre

0

Voici une solution fonctionnelle pour le moment mais elle est limitée et problématique car elle nécessite de convertir des collections en listes dans le modèle et les modèles ne sont pas sensibles au contexte.

Index1.aspx: Pour rendre une collection de Foos.

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IList<Foo>>" %> 
<asp:Content ContentPlaceHolderID="MainPlaceHolder" runat="server"> 
    <%:Html.DisplayForModel("List")%> 
</asp:Content> 

Shared \ DisplayTemplates \ List.ascx: Modèle de collection spécial.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IList>" %> 
<ul class="list"> 
<% for(int i = 0, count = Model.Count; i < count; i++) 
    { 
%>  <li><%:Html.DisplayFor(m => m[i])%></li> 
<% } 
%> 
</ul> 

Shared \ DisplayTemplates \ Foo.ascx: Modèle non contextuel pour Foo. Je préférerais toujours gérer ce scénario d'une manière similaire à la façon dont je l'ai décrit auparavant. Ainsi, le modèle de modèle peut déterminer lui-même comment il doit formater la sortie au lieu d'avoir à créer des modèles de cas spéciaux qui sont référencés par son nom par l'appelant.