Je pense que c'est assez simple, je n'arrive tout simplement 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, j'aimerais créer une table 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» d'obtenir le nom d'affichage ici?
la source
List<PersonNameViewModel>
vous avez unIEnumerable<PersonNameViewModel>
, alors il est également prudent d'utiliser l'expressionmodel => model.Names.First().FullName
. Est-ce correct? Cela dit, je pense que j'aime ledummyModel
meilleur exemple des trois. Sinon, vous pourriez avoir plusieurs propriétés dans lesquelles vous devez taper ou collermodel.Names[0].
. Là encore, vous devriez peut-être refactoriser la section en une vue partielle qui accepte leList
ouIEnumerable
comme modèle.FirstOrDefault()
travaille avec une liste vide.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>
la source
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; } } }
Utiliser ceci dans la vue est le même que son exemple. Je crée une seule instance d'un objet vide donc je ne crée pas une nouvelle instance à chaque fois que je référence Default .
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:
la source
DisplayNameFor
n'appelle jamais réellementget
la propriété pour, donc peu importe si vous créez une instance.Comme solution alternative, vous pouvez essayer:
Cela fonctionnera même si la liste est vide!
la source