DisplayNameFor () à partir de la liste dans le modèle

je crois que c'est assez simple, je n'arrive pas à trouver la bonne façon de montrer le nom d'affichage d'un élément dans une liste au sein de mon modèle.

mon modèle simplifié:

public class PersonViewModel
{
    public long ID { get; set; }

    private List<PersonNameViewModel> names = new List<PersonNameViewModel>();

    [Display(Name = "Names")]
    public List<PersonNameViewModel> Names { get { return names; } set { names = value; } }      
}

et noms:

public class PersonNameViewModel
{
    public long ID { get; set; }

    [Display(Name = "Set Primary")]
    public bool IsPrimary { get; set; }

    [Display(Name = "Full Name")]
    public string FullName { get; set; }
}

maintenant je voudrais faire une table pour montrer tous les noms pour une personne, et obtenir le DisplayNameFor FullName. Évidemment,

@Html.DisplayNameFor(model => model.Names.FullName);

ne fonctionnerait pas, et

@Html.DisplayNameFor(model => model.Names[0].FullName);  

se cassera s'il n'y a pas de noms. Est-il un "meilleur moyen" pour obtenir le nom complet ici?

63
demandé sur Jonesopolis 2013-12-28 01:10:29

3 réponses

cela fonctionne réellement, même sans articles dans la liste:

@Html.DisplayNameFor(model => model.Names[0].FullName)

cela fonctionne parce que MVC parse l'expression au lieu de l'exécuter. Cela lui permet de trouver la bonne propriété et l'attribut sans avoir besoin d'un élément dans la liste.

Il est intéressant de noter que le paramètre ( model ci-dessus) n'a même pas besoin d'être utilisé. Cela fonctionne aussi:

@Html.DisplayNameFor(dummy => Model.Names[0].FullName)

comme ceci:

@{ Namespace.Of.PersonNameViewModel dummyModel = null; }
@Html.DisplayNameFor(dummyParam => dummyModel.FullName)
108
répondu Tim S. 2013-12-27 21:34:09

il y a une autre façon de le faire, et je suppose que c'est plus clair:

public class Model
{
    [Display(Name = "Some Name for A")]
    public int PropA { get; set; }

    [Display(Name = "Some Name for B")]
    public string PropB { get; set; }
}

public class ModelCollection
{
    public List<Model> Models { get; set; }

    public Model Default
    {
        get { return new Model(); }
    }
}

et puis, dans la vue:

@model ModelCollection

<div class="list">
    @foreach (var m in Model.Models)
    {
        <div class="item">
            @Html.DisplayNameFor(model => model.Default.PropA): @m.PropA
            <br />
            @Html.DisplayNameFor(model => model.Default.PropB): @m.PropB
        </div>
    }
</div>
3
répondu T-moty 2015-06-14 01:50:57

j'aime la solution de T-moty. J'avais besoin d'une solution utilisant des génériques, donc ma solution est essentiellement celle-ci:

public class CustomList<T> : List<T> where T : new()
{       
    public static async Task<CustomList<T>> CreateAsync(IQueryable<T> source)
    {           
        return new CustomList<T>(List<T> list); //do whatever you need in the contructor, constructor omitted
    }

    private T defaultInstance = new T();

    public T Default
    {
        get { return defaultInstance; }
    }
}

utiliser ceci dans la vue est le même que son exemple. Je crée une instance unique d'un objet vide donc je ne crée pas une nouvelle instance à chaque fois que je me réfère à par défaut .

Note, la contrainte nouveau () est nécessaire pour appeler nouveau T () . Si votre modèle la classe n'a pas de contructeur par défaut, ou vous devez ajouter des arguments au constructeur que vous pouvez utiliser:

private T defaultInstance = (T)Activator.CreateInstance(typeof(T), new object[] { "args" });

Le point de vue aura un @modèle en ligne, comme:

@model CustomList<Namespace.Of.PersonNameViewModel.Model>
1
répondu shox 2018-03-23 19:21:57