私のモデルにはエンティティがあります
_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のタイトルを表示するにはどうすればよいですか?
@usingステートメントをビューに追加してCarrierタイプを指定できます。その後、モデルのCarriersプロパティをループする必要があります。
ビューは次のようになります。
@model CarrierIndexViewModel
@using Carrier
@foreach(Carrier c in Model.Carriers)
{
@Html.DisplayFor(model => c.Name)
}
ヘルパーメソッド、追加のコード、またはコレクションをループする必要がないことがわかりました。私は以下を使用しました:
_@Html.DisplayNameFor(model => model.Carriers.FirstOrDefault().Name)
_
FirstOrDefault()
がメタデータのみを探しているためnull
が返される場合でも、これは機能します。Name
プロパティ自体にはアクセスしません。
この回答に影響を与えた @ Kurian に感謝します。
同様の問題があります。列名を手動で入力したくないので、ヘルパーを作成しました。
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; }
}
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)
同様の要件がありましたが、@ 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では機能しません)。