Looping through a list in razor and adding a separ

2019-02-08 18:11发布

I have a list of items which I want to output in a razor view. Between each item I want to add a separator line, like this:

item1 | item2 | item3

The simplest way to loop through items is with a foreach:

@foreach(var item in Model.items){
  <span>@item.Name</span> | 
}

Unfortunately this adds an extra separator line at the end of the list. Is there a simple way to skip this last separator line?

4条回答
唯我独甜
2楼-- · 2019-02-08 18:21

Not sure if this is the simplest way, or if these is a more elegant way, but you could do something like;

@foreach ( var item in Model.items){
    <span>@item.Name</span> @(Model.items[Model.items.Count - 1] != item ? "|" : "")
}

So you are basically checking to see if the item is the last item in the list.

Not tried this code sample, so you might need to tweek it.

查看更多
放我归山
3楼-- · 2019-02-08 18:30

Keep a counter variable and inside the loop and check whether it is the last item or not.

@{ int counter=0; }
@foreach(var item in Model.items){
  counter++;
  <span>@item.Name</span>
  if(counter<Model.Items.Count) 
  {
    @Html.Raw("|")
  } 
}

and the short version is

@{ int counter=0; }
@foreach(var item in Model.items){
  counter++;
  <span>@item.Name</span> @(counter< Model.items.Count?"|":"")
 } 
查看更多
冷血范
4楼-- · 2019-02-08 18:39

Combining the other answers here with this article on inline templates, I came up with this helper method, which can be put in an extension class:

public static HelperResult Join<T>(this IEnumerable<T> list, Func<T, HelperResult> template, Func<T, HelperResult> separator)
{
    var first = true;
    var result = new HelperResult(writer =>
    {
        foreach (var item in list)
        {
            if (first == false)
                separator(item).WriteTo(writer);
            first = false;
            template(item).WriteTo(writer);
        }
    });

    return result;
}

The way to use it would then be

@Model.ListOfItems.Join(
    @<a href="@item.Href">
        @item.Name
    </a>, 
    @<text> | </text>)

This supports html in both the items and the separator.

查看更多
啃猪蹄的小仙女
5楼-- · 2019-02-08 18:44

You can use string.Join:

@Html.Raw(string.Join("|", model.Items.Select(s => string.Format("<span>{0}</span>", s.Name))))

Using string.Join negates the need to check for the last item.

You can mix this with a Razor @helper method for more complex markup:

@helper ComplexMarkup(ItemType item)
{ 
    <span>@item.Name</span>
}

@Html.Raw(string.Join("|", model.Items.Select(s => ComplexMarkup(s))))

You could even create a helper method to abstract the Html.Raw() and string.Join() calls:

public static HtmlString LoopWithSeparator
    (this HtmlHelper helper, string separator, IEnumerable<object> items)
{
    return new HtmlString
          (helper.Raw(string.Join(separator, items)).ToHtmlString());
}

Usage:

@Html.LoopWithSeparator("|",  model.Items.Select(s => ComplexMarkup(s)))
查看更多
登录 后发表回答