web-dev-qa-db-ja.com

詳細モデルについては、@ Html.DisplayNameFor

私のモデルにはエンティティがあります

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

ViewModelもあります

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

強く型付けされた(CarrierIndexViewModel)インデックスビューがあります。これは、PagingInfoを使用してCarrierのテーブルを表示することを想定しています。

Htmlヘルパーを使用して、テーブルのヘッダーにCarrier.Nameを表示しようとしています。このビューのモデルとしてIEnumerableを使用すると、@Html.DisplayFor(model => model.Name)

新しいCarrierIndexViewModelを使用して同じ結果を取得してCarrier.Nameのタイトルを表示するにはどうすればよいですか?

25
Alex

@usingステートメントをビューに追加してCarrierタイプを指定できます。その後、モデルのCarriersプロパティをループする必要があります。

ビューは次のようになります。

@model CarrierIndexViewModel
@using Carrier

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

ヘルパーメソッド、追加のコード、またはコレクションをループする必要がないことがわかりました。私は以下を使用しました:

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

FirstOrDefault()がメタデータのみを探しているためnullが返される場合でも、これは機能します。Nameプロパティ自体にはアクセスしません。

この回答に影響を与えた @ Kurian に感謝します。

39
Red Taz

同様の問題があります。列名を手動で入力したくないので、ヘルパーを作成しました。

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

次に、ビューでそれを呼び出します

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

Nameやリソースファイルなどの他の多くのカスタマイズを受け入れるDisplay属性を使用できることに注意してください。

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

originalDisplayNameFor拡張メソッドと一貫性のある動作に基づくアプローチを以下に示します。

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

そして、それがビューで使用できる方法です。

@Html.DisplayNameFor(m => m.Carriers, c => c.Name)
4
Deilan

同様の要件がありましたが、@ plurbyのソリューションが機能しないように、列挙できないクラスからプロパティの表示名を取得する必要がありました。私は、任意のタイプの新しいHtmlHelperを取得するために使用できる流暢な呼び出しを作成することで、これを解決しました。拡張機能とアダプターのコードは次のとおりです。

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

これを次のようなビューで使用できます。

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

利点の1つは、このアプローチがDisplayNameForだけでなく、すべてのHtmlHelper拡張機能で機能することです(ただし、適応されたHtmlHelperにはビューデータがありません。これはすべて、表示するため、適応したHtmlHelperでは機能しません)。

3
daveaglick