2012-02-21 13 views
22

Nel mio modello ho un'entità@ Html.DisplayNameFor per i dettagli del modello

public class Carrier 
{ 
public Guid CarrierId { get; set; } 
public string Name { get; set; } 
} 

Ho anche un ViewModel

public class CarrierIndexViewModel 
{ 
public IEnumerable<Carrier> Carriers { get; set; } 
public PagingInfo PagingInfo { get; set; } 
} 

Ho un fortemente tipizzato (CarrierIndexViewModel) Index View, che è supponiamo di mostrare una tabella di Carrier usando PagingInfo.

Sto cercando di utilizzare helper HTML per visualizzare Carrier.Name nel colpo di testa di mio tavolo Quando ho usato IEnumerable come modello per questo punto di vista ho avuto @Html.DisplayFor(model => model.Name)

Come posso ottenere lo stesso risultato utilizzando il mio nuovo CarrierIndexViewModel visualizzare il titolo per Carrier.Name?

risposta

8

È possibile aggiungere un'istruzione @using alla vista per specificare il tipo di operatore, quindi sarà necessario eseguire il ciclo attraverso la proprietà Carriers del modello.

tuo Vista avrà un aspetto simile ..

@model CarrierIndexViewModel 
@using Carrier 

@foreach(Carrier c in Model.Carriers) 
{ 
@Html.DisplayFor(model => c.Name) 
} 
17

Ho un problema simile, perché io non voglio scrivere i miei nomi delle colonne a mano così ho scritto un aiutante:

public static IHtmlString 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); 
} 

Poi nella vista ti chiami

@Html.DisplayColumnNameFor(Model.Carriers, m => m.Name) 

si prega di notare che è possibile utilizzare l'attributo display che accetta N ame e molte altre personalizzazioni come risorsa file ecc

public class Carrier 
{ 
    [Display(Name="Carrier ID")] 
    public Guid CarrierId { get; set; } 
    [Display(Name="Carrier Name")] 
    public string Name { get; set; } 
} 
+1

non ho ancora provato questo, ma penso che si può solo dire "m => m. Carrier [0] .Name ". Poiché utilizza metadati dalle espressioni lambda internamente, non dovrebbe importare se "Carrier" è nullo o vuoto. – Monstieur

+1

Posso suggerire un leggero ritocco? Se l'attributo Nome visualizzato non è stato applicato, ti consigliamo di restituire il nome della proprietà in questo modo: "restituisci nuovo MvcHtmlString (metadata.DisplayName ?? name)" – Darryl

+0

Mi piace l'idea alla base di questa soluzione, ma sento che sento piccoli allarmi si spengono quando ci penso (forse non dovrei pensarci :)). Se dovessi prendere il tempo per scrivere il valore di visualizzazione di una proprietà nel mio codice, perché non prendi solo il tempo e scrivi il valore visualizzato nella vista? Sembra che sia stato scritto più codice solo per impedire l'inserimento di valori in una vista, quando è davvero dove dovrebbe essere comunque. – phreak3eb

2

ho avuto un requisito analogo, ma avevo bisogno di ottenere i nomi di visualizzazione per oggetti di una classe non enumerabile diversa quindi la soluzione da @plurby non avrebbe funzionato . Ho finito per risolvere questo creando una chiamata fluente che può essere utilizzata per ottenere un nuovo HtmlHelper per qualsiasi tipo arbitrario. Il codice per l'estensione e l'adattatore è:

public static class HtmlHelpers 
{ 
    public static HtmlHelperAdapter<TModel> Adapt<TModel>(this HtmlHelper<TModel> helper) 
    { 
     return new HtmlHelperAdapter<TModel>(helper); 
    } 

    public class HtmlHelperAdapter<TModel> 
    { 
     private readonly HtmlHelper<TModel> _helper; 

     public HtmlHelperAdapter(HtmlHelper<TModel> helper) 
     { 
      _helper = helper; 
     } 

     public HtmlHelper<TNewModel> For<TNewModel>() 
     { 
      return new HtmlHelper<TNewModel>(_helper.ViewContext, new ViewPage(), _helper.RouteCollection); 
     } 
    } 
} 

È quindi possibile utilizzare questo nella vista in questo modo:

<td>@(Html.Adapt().For<MyOtherModel>().DisplayNameFor(m => m.SomeProperty))</td> 

Uno dei vantaggi è che questo approccio funziona per qualsiasi estensione HtmlHelper, non solo DisplayNameFor (ma tieni presente che l'HtmlHelper adattato non ha dati di visualizzazione poiché è tutto scritto in base al modello utilizzato nella vista e quindi non funzionerà con HtmlHelper adattato).

36

Ho trovato che non era necessario alcun metodo di supporto, codice aggiuntivo o ciclo della raccolta. Ho appena usato il seguente:

@Html.DisplayNameFor(model => model.Carriers.FirstOrDefault().Name) 

questo funziona ancora, anche se FirstOrDefault() sarebbero tornati null perché è solo alla ricerca di metadati, la proprietà Name in sé non è accessibile.

Mille grazie a @Kurian che ha ispirato questa risposta.

+0

Grazie. Proprio quello che stavo cercando. Se Carriers è una lista <>, puoi utilizzare Carriers [0] o Carriers.FirstOrDefault(). –

3

Qui è un approccio, che si basa sul metodo di estensione originaleDisplayNameFor e funziona coerente.

un metodo di estensione per HtmlHelper:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Web; 
using System.Web.Mvc; 

public static class HtmlHelperExtensions 
{ 
    public static MvcHtmlString DisplayNameFor<TModel, TEnumerable, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, IEnumerable<TEnumerable>>> enumerableExpression, Expression<Func<TEnumerable, TValue>> valueExpression) 
    { 
     var metadata = ModelMetadata.FromLambdaExpression(valueExpression, new ViewDataDictionary<TEnumerable>()); 
     string displayName = metadata.DisplayName ?? metadata.PropertyName ?? ExpressionHelper.GetExpressionText(valueExpression).Split('.').Last(); 
     return new MvcHtmlString(HttpUtility.HtmlEncode(displayName)); 
    } 
} 

Ed è così che potrebbe essere utilizzato in una vista:

@Html.DisplayNameFor(m => m.Carriers, c => c.Name) 
Problemi correlati