2012-10-17 14 views
21

Questo funziona per afferrare le intestazioni (non valori):Calling sovraccarico IEnumerable di DisplayNameFor

@model IEnumerable<SomeModel> 
... 
<th>@Html.DisplayNameFor(m => m.SomeModelProperty)</th> 

Che se SomeModelProperty erano:

[Display(Name = "An Excellent Header")] 
SomeModelProperty { get; set; } 

allora sarebbe visualizzare "un'intestazione eccellente" in l'intestazione th elemento.

si potrebbe pensare che questo non avrebbe funzionato perché il modello è IEnumerable, che non avrebbe un m.SomeModelProperty, ma funziona perché HtmlHelper ha un HtmlHelper<IEnumerable<TModel>> tale che il parametro della lambda è TModel, non IEnumerable<TModel>. Poiché ciò utilizza solo i metadati, non è necessario un articolo dalla raccolta. (Anche se intellisense su m. ti mentirà e ti farà pensare che sia una raccolta). Non sono sicuro quando è stato aggiunto questo fantastico sovraccarico, ma è piuttosto utile per Index.cshtml e non funziona con cose funky come @Html.DisplayNameFor(m => @Model.FirstOrDefault().SomeModelProperty) che voglio evitare.

http://msdn.microsoft.com/en-us/library/hh833697(v=vs.108).aspx

Tuttavia, non riesco a capire come ottenere questo al lavoro quando il mio modello non è IEnumerable, ma invece contiene IEnumerable come una proprietà, come ad esempio:

public class SomeList 
{ 
    public List<SomeModel> SomeModels { get; set; } 
    public int Page { get; set; } 
    public DateTime CurrentAsOf { get; set; } 
} 

ero sperando di essere esplicito con i parametri di tipo generico, ma penso che i parametri di tipo siano specificati dal motore che scorre verso il basso dall'HtmlHelper creato con la pagina. Posso dichiarare un nuovo HtmlHelper nella pagina o in qualche modo specificare esplicitamente i parametri del tipo?

Index.cshtml:

@model SomeList 
//No idea how to do this: 
@Html.DisplayNameFor<IEnumerable<SomeModel>>(m => m.SomeModelProperty) 
+2

Nel codice del ciclo nel file Razor, è possibile controllare se è il ** primo ** elemento nel ciclo e generare la sezione '' utilizzando le chiamate 'DisplayNameFor'. Questo 'if' sarebbe prima della parte in cui si producono i dati in un' tr'. – Gromer

+1

Sì, ho utilizzato questi tipi di soluzioni alternative sperando di passare da quello ora che DisplayNameFor supporta l'acquisizione dei metadati da IEnumerable – AaronLS

+0

Questa domanda ha una soluzione valida e funzionante (risposta accettata): http://stackoverflow.com/questions/20807869/displaynamefor-from-listobject-in-model – lxa

risposta

38

Un'altra soluzione simile che funziona anche se non ci sono righe potrebbero essere:

... 
@{var dummy = Model.FirstOrDefault(); } 
    <tr> 
     <th> 
      @Html.DisplayNameFor(model => dummy.SomeModelProperty) 
     </th> 
... 
+4

La chiamata è ambigua tra i seguenti metodi o proprietà: 'System.Web.Mvc.Html.DisplayNameExtensions.DisplayNameFor (System.Web.Mvc. HtmlHelper >, System.Linq.Expressions.Expression >) 'and' System.Web.Mvc.Html .DisplayNameExtensions.DisplayNameFor , int> ... –

+1

stesso problema come Oleg Sh ... –

+1

Qualcuno è riuscito a risolvere questo problema? – user3407039

5

Ho esattamente lo stesso problema perché sto usando ViewModels così ho un ViewModel con un IEnumerable di oggetti reali come proprietà.

Mi sono imbattuto in questo post in cui se si verifica la risposta il ragazzo ha creato il proprio HTMLHelper per risolvere questo problema http://forums.asp.net/t/1783733.aspx. La sua versione è:

public static MvcHtmlString DisplayColumnNameFor<TModel, TClass, TProperty>(
    this HtmlHelper<TModel> helper, IEnumerable<TClass> model, 
    Expression<Func<TClass, TProperty>> expression) 
{ 
    var name = ExpressionHelper.GetExpressionText(expression); 
    name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name); 
    var metadata = ModelMetadataProviders.Current.GetMetadataForProperty(
     () => Activator.CreateInstance<TClass>(), typeof(TClass), name); 

    return new MvcHtmlString(metadata.DisplayName); 
} 

Devi passare due argomenti enumerazione e di espressione, piuttosto che il normale solo espressione così si può preferire risposta @franz. Non riesco a vedere che sia comunque necessario passare 2 argomenti poiché è necessario conoscere la proprietà del modello di vista a cui si sta applicando l'espressione.