1

I've got a view that displays a list of items. Rather than display items in a grid, I'd like to display 4 items per page, each with an image and multiple properties, displayed in a unique layout.

So, I'd like a foreach to iterate through the items, and each item to get displayed in a div. I could put all the code in the loop, but I'd like to have a custom html helper extension to do this.

I came up with this,

public static MvcHtmlString DisplayViewerFor(this HtmlHelper helper, TestModel model, bool rightAligned = true) {
        if (model == null) {
            model = new TestModel();
        }

        var outterDiv = new TagBuilder("div");
        outterDiv.AddCssClass(rightAligned ? "item-display-right" : "item-display");

        var image = new TagBuilder("image");
        image.Attributes.Add("src", "Item/GetImage/" + model.ItemName);
        image.Attributes.Add("height", "150");

        var editorLabel = new TagBuilder("div");
        editorLabel.AddCssClass("editor-label");


        //LOOKING TO ADD CODE LIKE THIS HERE

        var labelContent= html.LabelFor({my model property here})
        editorLabel.InnerHtml += labelContent;

        //END OF ADD


        return new MvcHtmlString(outterDiv.ToString(TagRenderMode.EndTag));
    }

In my method above, I need to display a few more values, and I would like to use the Html.LabelFor and Html.DisplayFor helpers, but the methods aren't available and I'm not sure what to pass to them if they were.

I'm not sure if this is possible or not, but I thought I would ask.

EDIT I'm trying to use the html.LabelFor. See my code where I have updated it above, adding to it these two lines.

var labelContent= html.LabelFor({my model property here})
editorLabel.InnerHtml += labelContent;

You can see the code above.

EDIT 2

Here is the planned use for this Helper with dummied down view.

@model TestItemDisplayList

@{ ViewBag.Title = "Items"; Layout = "~/Views/Shared/_Layout.cshtml"; }

@foreach(var item in @model.Items){ @Html.DisplayViewerFor(item) }

Jeff Reddy
  • 5,551
  • 9
  • 55
  • 88
  • 1
    I'm not really sure what you are asking. Can you clarify? – Mikeb Dec 08 '11 at 12:43
  • Is there a paticular reason you want to use the LabelFor? All it does is generate a label and reads the metadata of the item to determine what the Display Name should be. – Nick Bork Dec 08 '11 at 15:02
  • That's exactly the reason for wanting to use it. Each item I'm using this helper for will have 10 properties. For each property I will display a LabelFor and DisplayFor. – Jeff Reddy Dec 08 '11 at 15:20
  • You are aware that you can get the model meta data and extract what the Display would be and generate your own label, correct? If you have a Reflector you could get the code from the LabelFor method. You could also go directly to the static LabelFor method: System.Web.Mvc.Html.LabelExtensions.LabelFor and pass it expressions to generate the label. – Nick Bork Dec 08 '11 at 15:27
  • I have the source code for MVC, so I can see how they are doing it. I could rewrite everything that is already done, but that's my reason for wanting to use the functionality that's already there. I've already started doing this myself, but I thought to myself, why don't I use what is already done for me. But maybe that's not possible. – Jeff Reddy Dec 08 '11 at 15:32
  • Would it not be easier to create a DisplayTemplate for the TestItemDisplayList and a seperate DisplayTemplate for the TestItem instead of trying to create HTML Helpers to generate all of the HTML for you? I ask this because the LabelFor takes TModel, TValue and an expression. Your helper doesn't have those attributes so it will be difficult to call "LabelFor". Here is a snippet of code how to get the display name, but it too takes the TModel and TValue: http://stackoverflow.com/questions/3885796/get-displayname-attribute-without-using-labelfor-helper-in-asp-net-mvc – Nick Bork Dec 08 '11 at 15:44
  • I'm up for anything. My TestItemDisplayList handles the rest of the page. This small part of the page will display 6 items, each within it's own identical div. I can use a helper or have considered a partial view for these items. Not sure of the best approach. – Jeff Reddy Dec 08 '11 at 15:51
  • By using Html.DisplayFor(mode => Model) instead of your custom HTML Helper MVC will look for a "DisplayTemplate" that is named the same as the TYPE of your model. If you are using a generic List, I would use one of the over loads for DisplayFor and specify the template name which to render your list. Your Display Template would perform the same logic/code as your HTML Helper. The biggest difference is you'll have a much easier time using the HTML Helpers that take an expression like Html.LabelFor. From my point of view you'll need two Display Templates, one for the list and one for the item. – Nick Bork Dec 08 '11 at 16:13
  • OK, that makes sense now. I'll work towards that solution. You can post your last comment as an answer and I'll accept it. I would appreciate it if you could throw in a bit of code for examples. Thanks. – Jeff Reddy Dec 08 '11 at 16:23

1 Answers1

4

You can use the Html.DisplayFor method to render a DisplayTemplate. One of the over loads for the method is to specify a template to use. You can modify your page code to read:

Page:

 @model TestItemDisplayList
 @{ ViewBag.Title = "Items"; Layout = "~/Views/Shared/_Layout.cshtml"; }
 @Html.DisplayFor(model => Model,"TestItemDisplayList")

Display Template for TestItemDisplayList

 @model TestItemDisplayList
 @* You could limit this loop to the first 4 items  *@
 @foreach(var item in model.Items){ @Html.DisplayFor(item => item) }

Display Template for TestModel

 @model TestModel
 <div class="item-display">
      <img src="@Url.Action("GetImage", "Image", new  { id = Model.ItemName})" height="150"/>
      <div class="editor-label">@Html.LabelFor(model => model.PropertyHere)</div>
 </div>

I assume that your URL for the image used the default route of {controller}/{action}/{id} so I used the Url.Action and specified your ID.

You could also get away witout using a DisplayTemplate for "TestItemDisplayList" and moving that code in to your page but I wasn't clear if you wanted to add logic in that to limit the number of pages.

Nick Bork
  • 4,831
  • 1
  • 24
  • 25