2012-02-21 69 views
22

在我的模型我有一個實體@ 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顯示載體表。

我試圖使用HTML幫助我的表中的頭 顯示Carrier.Name當我使用的IEnumerable作爲這個觀點我 @Html.DisplayFor(model => model.Name)

模型我怎樣才能使用我的新CarrierIndexViewModel相同的結果顯示Carrier.Name的標題?

回答

8

您可以在視圖中添加@using語句來指定載體類型,然後您需要遍歷模型的載體屬性。

你的看法會是這個樣子..

@model CarrierIndexViewModel 
@using Carrier 

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

我有一個類似的問題,因爲我不想手工輸入我的列名,所以我寫了一個幫手:

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) 

請注意,您可以使用它接受n個顯示屬性AME和許多其他自定義喜歡的資源文件等

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

我沒有試過,但是我想你可以說「米=> m.Carriers [0] .Name「。由於它在內部使用來自lambda表達式的元數據,因此如果「運營商」爲空或空則應該沒有關係。 – Monstieur 2013-03-28 09:29:46

+1

我可以建議稍微調整一下嗎?如果「顯示名稱」屬性尚未應用,則需要返回屬性名稱,如下所示:「return new MvcHtmlString(metadata.DisplayName ?? name)」 – Darryl 2013-04-05 17:44:57

+0

我喜歡這個解決方案背後的想法,但我覺得我聽到了當我想到它時,一些警報就會響起(也許我不應該考慮它:))。如果我要花時間在代碼中編寫屬性的顯示值,爲什麼不花時間在視圖中寫入顯示值?看起來更多的代碼是爲了防止將值插入視圖而編寫的,無論如何它確實是它應該在的位置。 – phreak3eb 2013-12-06 16:52:01

2

我也有類似的要求,但我需要從不同的非枚舉類獲得的屬性顯示的名稱,以便從@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> 

的好處之一是,這種方法適用於任何的HtmlHelper擴展工作,而不是隻是DisplayNameFor(但請記住,改編的HtmlHelper沒有任何視圖數據,因爲這些都是基於視圖中使用的模型輸入的,因此無法在改編的HtmlHelper中使用)。

36

我發現沒有必要使用輔助方法,額外的代碼或通過集合循環。我只是用了以下內容:

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

這仍然有效,即使FirstOrDefault()將返回null,因爲它只是想找元數據,該Name屬性本身不被訪問。

非常感謝@Kurian誰啓發了這個答案。

+0

謝謝。正是我一直在尋找的東西。如果運營商是列表<>,則可以使用運營商[0]或運營商.FirstOrDefault()。 – 2014-07-30 20:02:29

3

這裏有一個方法,它是基於DisplayNameFor擴展方法和工作一致

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)