42 votes

ASP.net MVC - Modèle d'Affichage pour une collection

J'ai le texte suivant le modèle MVC:

public class ParentModel
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }

    public IEnumerable<ChildModel> Children { get; set; }
}

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

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

Je peux alors créer un ChildModel.cshtml afficher le modèle et la méthode displayfor automatiquement itérer sur la liste.

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

@model IEnumerable<ChildModel>

<table>
    <tr>
        <th>Property 1</th>
        <th>Property 2</th>
    </tr>
    ...
</table>

Comment puis-je créer un Modèle d'Affichage qui a un modèle de type IEnumerable et ensuite appeler @Html.Méthode displayfor(m => m.Enfants) sans se plaindre sur le type de modèle se tromper?

63voto

Darin Dimitrov Points 528142

Comme ceci:

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

ou comme ceci:

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

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

@model IEnumerable<ChildModel>

<table>
    <tr>
        <th>Property 1</th>
        <th>Property 2</th>
    </tr>
    ...
</table>

8voto

Luke Puplett Points 4971

Dans ma question à propos de ne pas obtenir de sortie de points de vue, en fait, j'ai un exemple de modèle un modèle avec une collection de modèles enfants et ont tous rendu.

ASP.NET Modèles d'Affichage - Pas de sortie

Essentiellement, vous avez besoin de créer un modèle qui sous-classes List<T> ou Collection<T> et utiliser:

@model ChildModelCollection 

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

Dans votre modèle pour le modèle de la collection d'itérer et de rendre les enfants. Chaque enfant doit fortement typé, de sorte que vous pouvez créer vos propres types de modèles pour les articles, aussi, et des modèles pour ceux.

Donc, pour l'OP question:

public class ChildModelCollection : Collection<ChildModel> { }

Va faire un typage fort modèle c'est une collection qui peut être résolu à un modèle comme un autre.

8voto

swazza85 Points 381

C'est en réponse à Maslow commentaire. C'est ma première contribution à faire de même, donc je n'ai pas assez de réputation pour commentaire - d'où la réponse comme une réponse.

Vous pouvez définir la TemplateHint la propriété dans la ModelMetadataProvider. Ce serait de l'auto de raccordement d'un IEnumerable à un modèle que vous spécifiez. Je l'ai juste essayé dans mon projet. Le Code ci-dessous -

protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(CachedDataAnnotationsModelMetadata prototype, Func<object> modelAccessor)
    {
        var metaData = base.CreateMetadataFromPrototype(prototype, modelAccessor);
        var type = metaData.ModelType;

        if (type.IsEnum)
        {
            metaData.TemplateHint = "Enum";
        }
        else if (type.IsAssignableFrom(typeof(IEnumerable<object>)))
        {
            metaData.TemplateHint = "Collection";
        }

        return metaData;
    }

En gros, vous avez remplacer le "CreateMetadataFromPrototype' méthode de la "CachedDataAnnotationsModelMetadataprovider" et enregistrer votre type dérivé de préférence ModelMetadataProvider.

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

@model IEnumerable<object>
@{ 
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 });
}

De mon point de vue, j'ai tout simplement appeler @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 cela a été d'une certaine valeur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X