Enhancing the ASP.NET MVC View fornext loop

A common problem with the default ASP.NET MVC view engine, when rendering collections in a for/next construct is the inability to easily determine where you are in the loop. For example a common way of displaying a menu is to use unordered lists and produce the following markup:

<ul class="menu>
    <li class="first"><a href="/home">Home</a></li>
    <li class="selected"><a href="/page-1">Page 1</a></li>
    <li><a href="/page-2">Page 2</a></li>
    <li class="last"><a href="/page-3">Page 3</a></li>

With the basic for/next loop over an ICollection producing this output is rather difficult.

My solution is an extension method for ICollection that provides additional information about the loop.

public static class CollectionExtensions
    public static IEnumerable<LoopItem<TSource>> Loop<TSource>(this ICollection<TSource> self)
        if (self == null) throw new ArgumentNullException("self");

        var index = 0;
        var count = self.Count();

        foreach (var item in self)
            yield return new LoopItem<TSource>(item, index, count);

public class LoopItem<TSource>
    private int _count;

    internal LoopItem(TSource item, int index, int count)
        this.Value  = item;
        this.Index  = index;
        this._count = count;

    public TSource Value { get; private set; }

    public int Index { get; private set; }

    public bool IsOdd
        get { return !this.IsEven; }

    public bool IsEven
        get { return this.Index % 2 == 0; }

    public bool IsFirst
        get { return this.Index == 0; }

    public bool IsLast
        get { return this.Index == (this._count - 1); }

With this code in place we can now do generate the menu from a collection with:

    <% foreach(var item in menuList.Loop()) {
        var classes = "";
        if (item.IsFirst) classes += "first ";
        if (item.IsLast) classes += "last ";%>
        <li class="<%: classes %>" >
            <%: Html.ActionLink(item.Value.Action, item.Value.Title) %>
    <% } %>

This makes displaying lists of data with specific classes a lot easier and simplifies your views. This same piece of code can also be used for rendering tables with odd/even rows.



Comments are closed.

%d bloggers like this: