8

In my ViewModel there is a property that needs a 2 line label but when I place a <br /> in the DisplayName attribute the HTML code is printed to the page instead of being interpreted as a line break. Is there a way to get a DisplayName to have a line break in it?

View:

    <tr>
        <td>
            @Html.LabelFor(m => m.GrossGallons)
        </td>
        <td>
        </td>
    </tr>

ViewModel:

    [DisplayName("Gross Gallons <br /> (Max: 6,000)")]
    public decimal GrossGallons { get; set; }

Output trying to get:

Gross Gallons
(Max: 6,000)
alex
  • 6,818
  • 9
  • 52
  • 103
Matthew Verstraete
  • 6,335
  • 22
  • 67
  • 123
  • Are you using `@Html.EditorFor(...)`? – mxmissile Mar 12 '14 at 16:46
  • Yes, I am using `@Html.EditorFor()` to display the input option. – Matthew Verstraete Mar 12 '14 at 16:55
  • possible duplicate of [How to Insert Line Break using LabelFor in MVC](http://stackoverflow.com/questions/10478454/how-to-insert-line-break-using-labelfor-in-mvc) – Tommy Mar 12 '14 at 19:29
  • @MatthewVerstraete - take a look at Darins answer here - http://stackoverflow.com/questions/10478454/how-to-insert-line-break-using-labelfor-in-mvc. Basically, without resorting to hacks, you should make your own label creating Html helper so that you can render out the Html unencoded. I would simply use this everywhere in place of the standard Html.LabelFor so you don't have to track which labels have html and which ones don't – Tommy Mar 12 '14 at 19:31

5 Answers5

17

There is a simple way of doing this - use \n instead of <br />, and use CSS to make it work.

Model:

[DisplayName("Gross Gallons\n(Max: 6,000)")]
public decimal GrossGallons { get; set; }

CSS:

label { white-space: pre-wrap; }

I would recommend making the CSS selector as specific as possible, so as not to catch other labels (in case you're using labels by hand elsewhere, where your source code may contain whitespace). For example, in bootstrap I would've applied this to label.control-label.

You could also attach a more specific style to that label only, and style only that class.

@Html.LabelFor(m => m.GrossGallons, new { @class = "multiline-label" })
Richard
  • 29,854
  • 11
  • 77
  • 120
1

I can think of a few options.

1) You could use @Html.Raw(). You can replace the string I have entered with a reference to a string.

@Html.Raw("Gross Gallons <br /> (Max: 6,000)");

1a) If you need to set it in the DisplayName attribute, then you might try using Html.Raw() but accessing the value through reflection. (Note: I haven't tried this, so don't know if it is possible)

2) You could use css styling to force the line to wrap where you want it to.

3) You could create a custom extension method or custom attribute to do this for you.

ken4z
  • 1,340
  • 1
  • 11
  • 18
  • 1
    1: That would defeat the purpose of using the `@Html.LabelFor`. 2: I really don't think using a CSS hack would be either efficient or proper to do. 3: I had thought about a custom extension but I was hoping there might be a simpler MVC solution. – Matthew Verstraete Mar 12 '14 at 16:57
0

you can use @Html.Raw(), I think this is the most simple way.

Sporule
  • 79
  • 1
  • 1
  • 8
  • 1
    That would defeat the purpose of using the `@Html.LabelFor`. – Matthew Verstraete Mar 12 '14 at 16:56
  • @Html.LabelFor is not @Html.Raw() – Sporule Mar 12 '14 at 17:44
  • @Html.LabelFor is – Sporule Mar 12 '14 at 17:45
  • I know the difference between the too HTML helpers. In my example I use the `@Html.LabelFor()` because I want the code to generate the `` tag. Moving to use the `@Html.Raw` defeats the entire reason of using `@Html.LabelFor()` in the first place. I am not even sure you could pass in the model and get the `DisaplyName` attribute to be parsed by the `@Html.Raw` helper. – Matthew Verstraete Mar 12 '14 at 17:51
0

It's not pretty, but you could use EditorTemplates and create a _layout.cshtml that all your Templates use. Then use this to pull/display the DisplayName:

<div class="form-group">
    <label for="@ViewData.ModelMetadata.PropertyName">
        @Html.Raw(ViewData.ModelMetadata.GetDisplayName())
    </label>
    @RenderBody()
    @Html.ValidationMessageFor(x => x)
</div>

The serious drawback to this is you would have to create EditorTemplates for each of your types like this sample string.cshtml template:

@model string
@{
    Layout = "_Layout.cshtml";
}
@Html.TextBoxFor(x => x, new { @class="form-control" })

A little off-topic but going this route allows me to encapsulate wrapping HTML around my form elements, so my forms in the views end up really simple like this:

<fieldset>
  @Html.EditorFor(x => x.Email)
  @Html.EditorFor(x => x.Address1)
  @Html.EditorFor(x => x.Address2)
  @Html.EditorFor(x => x.City)
</fieldset>
mxmissile
  • 11,464
  • 3
  • 53
  • 79
  • Why are you placing the label and validation message into the layout page instead of just right in the page where all the other form markup is at? – Matthew Verstraete Mar 12 '14 at 17:17
  • Because I only have to do it there once versus every time everywhere else. @Html.EditorFor() takes care of that for me. – mxmissile Mar 12 '14 at 17:21
  • Again, its not pretty. :-) I dont like the built in EditorFor templates so I usually end up writing my own for all the types anyway. Therefore its not a problem for me, however if you are fine with the built in, well then a lot of extra work.... – mxmissile Mar 12 '14 at 17:22
  • But placing that in the layout template would screw up pages not displaying the form data or any form data that is using a model that does not have the `DisplayPropery` attribute, right? – Matthew Verstraete Mar 12 '14 at 17:23
  • Yes and No, if you use EditorFor it would drop in the Layout stuff. I only use EditorFor inside a standard form. `GetDisplayName()` returns `PropertyName` if the `DisplayName` attribute is not used. – mxmissile Mar 12 '14 at 17:28
0

If use LabelFor(), another "possible" solution is to implement your own using the original source as a guide.

Replace

tag.SetInnerText(resolvedLabelText);

with

tag.InnerHtml = resolvedLabelText;
mxmissile
  • 11,464
  • 3
  • 53
  • 79