简体   繁体   中英

ASP.net add text after Html.DisplayFor

I am trying to add some text after @Html.DisplayFor() helper in ASP.net MVC 5 view, but can't get it to work.

My code:

@foreach (var item in Model.Changes)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Value)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Date)
        </td>
        <td>
            @foreach (var tag in item.Tags)
            {
                @Html.DisplayFor(modelItem => tag.Name)
            }
        </td>

    </tr>
    }

The problem is the Tags IEnumerable. It renders like this: 我得到了什么

I want to separate tags so that they are readable easily (eg. "Tag1, Tag2, ...") or with pipe sign (" | "). I guess this is easily done, but as I can't C#/ASP well I can't get it to work. Tried adding text just after @Html.DisplayFor(modelItem => tag.Name) but this gives me compilation error.

If this changes anything, Tags are added with Tag-it .

One solution could be:

<td>
    @foreach (var tag in item.Tags)
    {
        @Html.DisplayFor(modelItem => tag.Name)<text>|</text>
    }
</td>

I would move the display logic to your model by creating a new property in your model:

@using System.Linq;

...

public TagDisplayText
{
    get
    {
        return string.Join(", ", Tags.Select(x => x.Name));
    }
}

and then call this property from your view:

<td>
    @Html.DisplayFor(m => m.TagDisplayText)
</td>

Going further down the line. You can also do like this. If you want to apply css / modify dom element.

<span class="sometext">@Html.DisplayFor(modelItem => tag.Name) some text </span>

You should consider using display templates.

To create a display template you will need to add new view in Views/Shared/DisplayTemplates folder. In your example you can create view named "Tags" that could look something like that:

@model IEnumerable<Tag>

@{
    var tags = Model != null ? Model.ToList() : new List<Tag>();
    var tagsCount = tags.Count;
}

@for (int i = 0; i < tagsCount; i++)
{
    @tags[i].Name
    if (i < tagsCount - 1)
    {
        <text> | </text>
    }
}

And then in your main view:

@Html.DisplayFor(x => item.Tags, "Tags")

You can also think about making such code more generic and reusable. Views can't have generic models, so you can create a wrapper for that:

 public interface IDisplayItem
 {
     dynamic Item { get; }
     Func<string> DisplayValueFn { get; }
 }

 public class DisplayItem<T> : IDisplayItem
 {
     public T Item { get; set; }

     dynamic IDisplayItem.Item
     {
         get { return Item; }
     }

     public Func<T, string> DisplayValueFn { get; set; }

     Func<string> IDisplayItem.DisplayValueFn
     {
         get { return () => DisplayValueFn(Item); }
     }
 }

Then display template will look like that:

@model IEnumerable<IDisplayItem>

@{
    var items = Model != null ? Model.ToList() : new List<IDisplayItem>();
    var itemsCount = items.Count;
}

@for (int i = 0; i < itemsCount; i++)
{
    @items[i].DisplayValueFn()
    if (i < itemsCount - 1)
    {
        <text> | </text>
    }
}

And you can show tags from your example this way:

var tags = item.Tags
    .Select(tag => new DisplayItem<Tag>
    {
        Item = tag,
        DisplayValueFn = x => x.Name
    });

@Html.DisplayFor(x => tags, "Collection")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM