ASP.net MVC – Modèle d’affichage pour une collection

J’ai le modèle suivant dans MVC:

public class ParentModel { public ssortingng Property1 { get; set; } public ssortingng Property2 { get; set; } public IEnumerable Children { get; set; } } 

Lorsque je veux afficher tous les enfants du modèle parent, je peux le faire:

 @Html.DisplayFor(m => m.Children) 

Je peux alors créer un modèle d’affichage ChildModel.cshtml et DisplayFor va parcourir automatiquement la liste.

Que faire si je veux créer un modèle personnalisé pour IEnumerable?

 @model IEnumerable  ... 
Property 1 Property 2

Comment créer un modèle d’affichage ayant un type de modèle IEnumerable , puis appeler @Html.DisplayFor(m => m.Children) sans que le type de modèle ne soit erroné?

Comme ça:

 @Html.DisplayFor(m => m.Children, "YourTemplateName") 

ou comme ça:

 [UIHint("YourTemplateName")] public IEnumerable Children { get; set; } 

où évidemment vous auriez ~/Views/Shared/DisplayTemplates/YourTemplateName.cshtml :

 @model IEnumerable  ... 
Property 1 Property 2

Ceci est en réponse au commentaire de Maslow. Ceci est ma première consortingbution à SO, donc je n’ai pas assez de réputation pour commenter – d’où la réponse comme réponse.

Vous pouvez définir la propriété ‘TemplateHint’ dans le ModelMetadataProvider. Cela raccorderait automatiquement tout IEnumerable à un modèle que vous spécifiez. Je viens de l’essayer dans mon projet. Code ci-dessous –

 protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(CachedDataAnnotationsModelMetadata prototype, Func modelAccessor) { var metaData = base.CreateMetadataFromPrototype(prototype, modelAccessor); var type = metaData.ModelType; if (type.IsEnum) { metaData.TemplateHint = "Enum"; } else if (type.IsAssignableFrom(typeof(IEnumerable))) { metaData.TemplateHint = "Collection"; } return metaData; } 

En principe, vous remplacez la méthode ‘CreateMetadataFromPrototype’ de ‘CachedDataAnnotationsModelMetadataProvider’ et enregistrez votre type dérivé en tant que ModelMetadataProvider préféré.

Dans votre modèle, vous ne pouvez pas accéder directement au ModelMetadata des éléments de votre collection. J’ai utilisé le code suivant pour accéder à ModelMetadata pour les éléments de ma collection –

 @model IEnumerable @{ var modelType = Model.GetType().GenericTypeArguments[0]; var modelMetaData = ModelMetadataProviders.Current.GetMetadataForType(null, modelType.UnderlyingSystemType); var propertiesToShow = modelMetaData.Properties.Where(p => p.ShowForDisplay); var propertiesOfModel = modelType.GetProperties(); var tableData = propertiesOfModel.Zip(propertiesToShow, (columnName, columnValue) => new { columnName.Name, columnValue.PropertyName }); } 

À mon avis, j’appelle simplement @ Html.DisplayForModel () et le modèle est chargé. Il n’est pas nécessaire de spécifier «UIHint» sur les modèles.

J’espère que c’était utile.

Dans ma question sur la non-sortie des vues, j’ai un exemple de la façon de modéliser un modèle avec une collection de modèles enfants et de les rendre tous.

Modèles d’affichage ASP.NET – Pas de sortie

Essentiellement, vous devez créer un modèle qui regroupe List ou Collection et l’utiliser:

 @model ChildModelCollection @foreach (var child in Model) { Html.DisplayFor(m => child); } 

Dans votre modèle pour le modèle de collection pour itérer et rendre les enfants. Chaque enfant doit être fortement typé. Vous pouvez également créer vos propres types de modèle pour les éléments et disposer de modèles pour ceux-ci.

Donc, pour la question OP:

 public class ChildModelCollection : Collection { } 

Fera un modèle fortement typé, une collection qui peut être résolue en un modèle comme un autre.

La véritable “réponse valide” est -IMHO- de ne pas répondre correctement à la question. Je pense que l’OP cherche un moyen d’avoir un modèle de liste qui se déclenche sans spécifier l’UIHint.

Des trucs magiques font presque le boulot

Une certaine magie charge la vue correcte pour un type spécifié .
Un peu plus de magie charge la même vue pour une collection d’ un type spécifié.
Il devrait y avoir de la magie qui répète la même vue pour une collection d’un type spécifié.

Changer le comportement actuel?

Ouvrez votre désassembleur préféré. La magie se produit dans System.Web.Mvc.Html.TemplateHelpers.ExecuteTemplate . Comme vous pouvez le voir, il n’ya pas de points d’extensibilité pour modifier le comportement. Peut-être qu’une requête pull à MVC peut aider …

Aller avec la magie actuelle

Je suis venu avec quelque chose qui fonctionne. Créez un modèle d’affichage ~/Views/Shared/DisplayTemplates/MyModel.cshtml .

Déclarez le modèle comme object type.

Si l’object est une collection, effectuez une itération et restituez le modèle. Si ce n’est pas une collection, affichez l’object.

 @model object @if (Model is IList) { var models = (IList)Model; 
    @foreach (var item in models) { @Html.Partial("DisplayTemplates/MyModel", item) }
} else { var item = (MyModel)Model;
  • @item.Name
  • } }

    Maintenant, DisplayFor fonctionne sans UIHint .