En mi modelo que tiene una Entidad

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

También tengo un ViewModel

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

Tengo un inflexible (CarrierIndexViewModel) Vista de Índice, que se supone que debe mostrar una tabla de Portador mediante PagingInfo.

Estoy tratando de utilizar Html helper para mostrar Transportista.Nombre en mi encabezado de la tabla
Cuando he usado IEnumerable como un modelo para este punto de vista me había
@Html.DisplayFor(model => model.Name)

Cómo puedo obtener el mismo resultado usando mi nuevo CarrierIndexViewModel para mostrar el título de Transportista.Nombre?

InformationsquelleAutor Alex | 2012-02-21

5 Comentarios

  1. 8

    Puede agregar un @con declaración de su punto de Vista para especificar el tipo de Portador, entonces usted necesitará un bucle a través de su Modelo de Transportistas de la propiedad.

    Su Vista se verá algo como..

    @model CarrierIndexViewModel
    @using Carrier
    
    @foreach(Carrier c in Model.Carriers)
    {
     @Html.DisplayFor(model => c.Name)
    }
  2. 38

    Me encontré con que no había necesidad de métodos auxiliares, código adicional o de bucle a través de la colección. Acabo de utilizar lo siguiente:

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

    Esto todavía funciona incluso si FirstOrDefault() volvería null ya que está sólo en busca de datos de metadatos, el Name propiedad en sí no es accesible.

    Muchas gracias a @Kurian que inspiró esta respuesta.

    • Gracias. Justo lo que he estado buscando. Si el portador es una lista de<>, usted puede utilizar los Transportistas[0] o de los Transportistas.FirstOrDefault() .
  3. 17

    Tengo un problema similar, porque no quiero escribir mi columna de nombres de mano, por lo que escribió un ayudante:

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

    A continuación, en la vista que llamamos

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

    Por favor, tenga en cuenta que puede utilizar el atributo de Visualización que acepta el Nombre y muchos otros de personalización como el archivo de Recursos, etc.

    public class Carrier
    {
      [Display(Name="Carrier ID")]
      public Guid CarrierId { get; set; }
      [Display(Name="Carrier Name")]
      public string Name { get; set; }
    }
    • No he probado este, pero creo que se puede decir «m => m.Portadores[0].Nombre». Ya que utiliza los metadatos de las expresiones lambda internamente no importa si los «Portadores» es nulo o vacío.
    • Puedo sugerir un leve ajuste? Si la Pantalla de Nombre de atributo no se ha aplicado, usted querrá regresar el nombre de la propiedad así: «volver de nuevo MvcHtmlString( metadatos.DisplayName ?? nombre )»
    • Me gusta la idea detrás de esta solución, pero tengo la sensación de escuchar a poco alarmas se apagan cuando me pongo a pensar (tal vez yo no debería pensar acerca de ello 🙂 ). Si yo iba a tomar el tiempo para escribir el valor de la pantalla para una propiedad en mi código, ¿por qué no acaba de tomar el tiempo y escribir el valor de la pantalla en la vista? Parece más código fue escrito sólo para evitar la inserción de los valores en una vista, cuando eso es realmente lo que debería ser de todos modos.
    • Si quieres hardcore el valor de hacerlo. He utilizado este enfoque para que yo pueda localizar la [Pantalla(Name=»nombre de Algunos»)] y para evitar codificar. Puedes echar un vistazo aquí para el *.resx solución stackoverflow.com/a/20383378/1241400
    • Aceptar que es un enfoque mucho mejor. Incluso mejor soporta la localización! 🙂
    • Si TClass no tiene un público constructor sin parámetros, Activator.CreateInstance fallará. En su lugar, utilice default(TClass).

  4. 3

    Aquí es un enfoque, que se basa en la original DisplayNameFor método de extensión y obras consistentes.

    Un método de extensión para 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));
        }
    }

    Y eso es lo que podría ser utilizado en una vista:

    @Html.DisplayNameFor(m => m.Carriers, c => c.Name)
  5. 2

    Tuve un requisito similar, pero yo necesitaba para obtener los nombres de visualización de propiedades de una diferente y no enumerable de la clase, de modo que la solución de @plurby no hubiera funcionado. Me terminó de resolver esto mediante la creación de un fluido de llamada que puede ser utilizado para obtener una nueva HtmlHelper para cualquier tipo arbitrario. El código de la extensión y el adaptador es:

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

    Usted puede utilizar esto en la vista como este:

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

    Una de las ventajas es que este método funcionará para cualquier HtmlHelper extensión, no sólo DisplayNameFor (pero tenga en cuenta que la adaptación HtmlHelper no tiene ningún vista de los datos, ya que todo está escrito basado en el modelo utilizado en la vista y por lo tanto no va a funcionar en la adaptación HtmlHelper).

Dejar respuesta

Please enter your comment!
Please enter your name here