Define a DisplayTemplate for a Custom Type

437 Views Asked by At

Is it possible to specify the Display Template name when defining a property Type?

For example, I have some classes:

public interface IFoo {}
public class Foo : IFoo {}
public class Bar : IFoo {}

Then I have a Model:

public class MyModel{
    IFoo IFooExample {get;set;}
}

Then I want to render IFooExample in my View:

@model MyModel

@Html.DisplayFor(x => x.IFooExample)

Foo and Bar can share the same Display Template, ie ~/Views/Shared/DisplayTemplates/IFoo.cshtml. How can I plug this logic into Mvc so that I don't have to either a) create Foo.cshtml and Bar.cshtml or b) from my View call DisplayFor with an overload for the view (@Html.DisplayFor(x => x.IFooExample, "IFoo.cshtml") ).

I also don't want to decorate my Model with a UIHint attribute. I'd really like to specify the information on the definition of Foo and Bar:

[UIHint("IFoo.cshtml")]
public class Foo : IFoo{}

[UIHint("IFoo.cshtml")]
public class Bar : IFoo{}

But UIHints can't be applied at the class level. So is there another way to do this?

1

There are 1 best solutions below

0
On

You simply need to create a new DisplayFor HtmlHelper extension method which is specific to the interface IFoo, and, inside it, display the desired template. For example:

public static class DisplayForExtensions
{
    public static MvcHtmlString DisplayFor<TModel>(this HtmlHelper<TModel> html,
        Expression<Func<TModel, IFoo>> propertySelector)
    {
        return html.DisplayFor(propertySelector, "IFoo.cshtml");
    }
}

This extension method is more specific than the original ones, which accept any kind of value, not specifically an IFoo property.

Remember that this extension method must be visible in your razor templates. To do so you can:

  • include the namespace with an @using in each desired Razor template
  • include it in the web.config, creating a new <add namespace="Your extension class namespace" /> under <namespaces>, so that it's available to all razor templates