Je crois que c'est assez simple, je n'arrive pas à trouver la bonne façon d'afficher le nom d'affichage d'un élément dans une liste 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 créer un tableau pour afficher tous les noms d'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. Existe-t-il un "meilleur moyen" pour obtenir le nom d'affichage ici?
Cela fonctionne réellement, même sans éléments dans la liste:
@Html.DisplayNameFor(model => model.Names[0].FullName)
Cela fonctionne parce que MVC analyse 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 convient 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 cela:
@{ Namespace.Of.PersonNameViewModel dummyModel = null; }
@Html.DisplayNameFor(dummyParam => dummyModel.FullName)
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>
J'aime la solution de T-moty. J'avais besoin d'une solution utilisant des génériques donc ma solution est essentiellement la suivante:
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; }
}
}
Son utilisation dans la vue est identique à son exemple. Je crée une seule instance d'un objet vide, donc je ne crée pas de nouvelle instance chaque fois que je fais référence par défaut.
Notez que la contrainte new () est nécessaire pour appeler new T (). Si votre classe de modèle n'a pas de constructeur par défaut, ou si vous devez ajouter des arguments au constructeur, vous pouvez utiliser ceci:
private T defaultInstance = (T)Activator.CreateInstance(typeof(T), new object[] { "args" });
La vue aura une ligne @ model comme:
@model CustomList<Namespace.Of.PersonNameViewModel.Model>