Reputation: 15513
I have a class like this with a generic type:
Document<T>
This class is part of a view model
public class MyViewModel
{
public IEnumerable<Document<T>> Documents {get;set;}
}
I'd like to use DisplayFor to dispatch to the appropriate template in the view.cshtml
@model MyViewModel
foreach(var vm in Model.Documents)
{
@Html.DisplayFor(vm)
}
But I don't know how to create templates in Shared/DisplayTemplates that have a name of the class, but the C# name omits the generic parameters:
Document`1
But this is insufficent, as it doesn't identify the full type structure.
Is there a way to use DisplayFor with DisplayTemplates and Generic Types?
Upvotes: 4
Views: 2813
Reputation: 9155
You can do something like this:
@foreach(var vm in Model.Documents)
{
Type type = vm.GetType().GetGenericArguments()[0];
var templateName = "Document_" + type.Name;
@Html.DisplayFor(model => vm, templateName)
}
And, then, your DisplayTemplates will be named like "Docuement_Entity1.cshtml", "Document_Entity2.cshtml",... where Entity1 and Entity2 are your generic argument types.
Alternatively, you can create a TemplateName property for the Document class, set it just like in the code above, and use it in your View like this:
@foreach(var vm in Model.Documents)
{
@Html.DisplayFor(model => vm, vm.TemplateName)
}
UPDATE:
If you want to use an Html Helper, you can do something like this:
public static MvcHtmlString DisplayGenericFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
{
var modelType = helper.ViewData.Model.GetType();
if (!modelType.IsGenericType)
throw new ArgumentException();
Type genericType = modelType.GetGenericArguments()[0];
var templateName = modelType.Name.Split('`').First() + "_" + genericType.Name;
return helper.DisplayFor<TModel, TValue>(expression, templateName);
}
Upvotes: 6