DisplayNameFor () Da elenco nel modello

Credo che sia abbastanza semplice, non riesco proprio a trovare il modo giusto per mostrare il nome visualizzato di un elemento all’interno di un elenco all’interno del mio modello.

Il mio modello semplificato:

public class PersonViewModel { public long ID { get; set; } private List names = new List(); [Display(Name = "Names")] public List Names { get { return names; } set { names = value; } } } 

e nomi:

 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; } } 

Ora mi piacerebbe creare un tavolo per mostrare tutti i nomi di una persona e ottenere il NomeNomeVisualizzazioneFor. Ovviamente,

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

non avrebbe funzionato, e

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

si romperà se non ci sono nomi. C’è un “modo migliore” per ottenere il nome visualizzato qui?

Questo funziona davvero, anche senza elementi nell’elenco:

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

Funziona perché MVC analizza l’espressione anziché eseguirla effettivamente. Questo gli permette di trovare quella proprietà e attributo giusti senza che ci sia bisogno di essere un elemento nell’elenco.

Vale la pena notare che il parametro ( model sopra) non ha nemmeno bisogno di essere utilizzato. Anche questo funziona:

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

Come fa questo:

 @{ Namespace.Of.PersonNameViewModel dummyModel = null; } @Html.DisplayNameFor(dummyParam => dummyModel.FullName) 

C’è un altro modo per farlo, e credo che sia più chiaro:

 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 Models { get; set; } public Model Default { get { return new Model(); } } } 

E poi, nella vista:

 @model ModelCollection 
@foreach (var m in Model.Models) {
@Html.DisplayNameFor(model => model.Default.PropA): @m.PropA
@Html.DisplayNameFor(model => model.Default.PropB): @m.PropB
}

Mi piace la soluzione di T-moty. Avevo bisogno di una soluzione usando i generici, quindi la mia soluzione è essenzialmente questa:

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

Usarlo nella vista è lo stesso del suo esempio. Creo una singola istanza di un object vuoto in modo che non crei una nuova istanza ogni volta che faccio riferimento a Predefinito .

Nota, il nuovo vincolo () è necessario per chiamare il nuovo T () . Se la class del modello non ha un contructor di default, o devi aggiungere argomenti al costruttore puoi usare questo:

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

La vista avrà una linea @model simile a:

 @model CustomList