ASP.NET MVC tab-based navigation

December 16, 2010 09:08 in , ,

First of all this is not one of those JavaScript tab navigation scripts. Actually we are going to use no JavaScript.

Each tab is going to be linked to an ASP.NET MVC controller action. This is how end result is going to look like:

ASP.NET MVC Tabbed Navigation

And here is the sample website I have created which contains everything you need:

So how exactly this works?

We have a HTML helper method named SimpleNav that renders the HTML to the master page. This is how it is called:

<div id="menubar">
    <%= Html.SimpleNav(new[] {
        new SimpleNavItem{Text="Home", Action="Index", Controller = "Home"},
        new SimpleNavItem{Text="Blog", Action="Index", Controller = "Blog", GetSelected = ((a, c) => (c == "Blog"))},
        new SimpleNavItem{Text="About", Action="About", Controller = "Home", GetSelected = ((a, c) => c == "Home" && a == "About")},
        new SimpleNavItem{Text="Contact", Action="Contact", Controller = "Home", GetSelected = ((a, c) => c == "Home" && a == "Contact")}
    }) %>  
</div>

The code for this helper method is very straightforward. It simply generates an unordered list of links:

public static string SimpleNav(this HtmlHelper html, IEnumerable<SimpleNavItem> navItems)
{
    var urlHelper = new UrlHelper(html.ViewContext.RequestContext);
    string controller = html.ViewContext.RouteData.Values["controller"].ToString();
    string action = html.ViewContext.RouteData.Values["action"].ToString();

    TagBuilder ul = new TagBuilder("ul");
    ul.AddCssClass("clearfix");

    StringBuilder listBuilder = new StringBuilder();
    TagBuilder li = null;
    TagBuilder a = null;
    foreach (var item in navItems)
    {
        a = new TagBuilder("a");
        a.Attributes.Add("href", urlHelper.Action(item.Action, item.Controller));
        a.InnerHtml = item.Text;

        li = new TagBuilder("li");
        if (item.GetSelected != null && item.GetSelected(action, controller))
            li.AddCssClass("sel");
        li.InnerHtml = a.ToString();

        listBuilder.Append(li.ToString());
    }

    ul.InnerHtml = listBuilder.ToString();

    return ul.ToString();
}
public class SimpleNavItem
{
    public string Text { get; set; }
    public string Action { get; set; }
    public string Controller { get; set; }
    public Func<string, string, bool> GetSelected { get; set; }
}

The interesting part of the above code may be GetSelected which is an anonymous method. You might want a tab gets highlighted on certain conditions for example highlight the Blog tab for all Actions of the related Controller. The method accepts two Strings which are name of the current Controller and Action and returns a Boolean which indicated if the tab should be highlighted or not.

The final step which I like the most is to make it pretty. By using a simple background image and a small amount of CSS magic you can easily achieve this:

#menubar {
    border-bottom: solid 3px #8CC740;
    padding-left: 10px;
}
#menubar li {
    display: inline;
}
#menubar li a {
    float: left;    
    line-height: 21px;
    width: 80px;
    margin-right: 1px;
    background: url(tabs.gif) no-repeat 0px 0px;    
    color: #444;    
    text-align: center;
    text-decoration: none;
}
#menubar li a:hover {
    background-position: 0px -22px;
    text-decoration: none;
}
#menubar li.sel a {
    background-position: 0px bottom;
    color: #fff;
}

This may not be the most complete solution but it has helped me in so many projects. Hopefully it does the same for you.

ASP.NET GridView makeover using CSS

January 23, 2009 10:11 in , ,

I use ASP.NET GridView in my projects a lot. It is a great control with powerful functionality that can be customized in many ways. GridView has many settings that you can use to alter its look and also offers you some predefined formats that you can use (you can access them by clicking Auto Format link on the bottom of GridView properties panel). What formats do is to modify different styling properties of the GridView such as row style, alternate row style, header style and so on.

What is the problem?

Modifying different styling properties of the GridView control to create a custom look may be simple but has a few problems. The biggest problem is the styling information will be included in the generated html and that causes the resulting page size to be bigger. Another problem is that you have to modify a lot of properties to find a look that satisfies you. Also later if you want to do a change in the look of GridView you have to modify all instances of the controls in your website.

The Solution

The good news is that you can use CSS to control the look of the GridView easily. You will add a few hooks to the GridView control and you are ready to write some CSS to completely change the look of the control. I have created a sample website to demonstrate this; you can download it from the link below.

Modifying GridView look is very easy using CSS. By spending a little time you can create really cool styles that can reuse in your projects easily. Following picture is a screen shot of the final result of this article.

ASP.NET GridView

Implementation

Here's the GridView control syntax in our ASP.NET page. The only properties that we need to change to provide the custom look are CssClass, PagerStyle-CssClass and AlternatingRowStyle-CssClass.

<asp:GridView ID="gvCustomres" runat="server"
    DataSourceID="customresDataSource" 
    AutoGenerateColumns="False"
    GridLines="None"
    AllowPaging="true"
    CssClass="mGrid"
    PagerStyle-CssClass="pgr"
    AlternatingRowStyle-CssClass="alt">
    <Columns>
        <asp:BoundField DataField="CompanyName" HeaderText="Company Name" />
        <asp:BoundField DataField="ContactName" HeaderText="Contact Name" />
        <asp:BoundField DataField="ContactTitle" HeaderText="Contact Title" />
        <asp:BoundField DataField="Address" HeaderText="Address" />
        <asp:BoundField DataField="City" HeaderText="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" />
    </Columns>
</asp:GridView>
<asp:XmlDataSource ID="customresDataSource" runat="server" DataFile="~/App_Data/data.xml"></asp:XmlDataSource>

The CSS to provide the custom look is very short and you can change the view and create new looks really easy.

.mGrid { 
    width: 100%; 
    background-color: #fff; 
    margin: 5px 0 10px 0; 
    border: solid 1px #525252; 
    border-collapse:collapse; 
}
.mGrid td { 
    padding: 2px; 
    border: solid 1px #c1c1c1; 
    color: #717171; 
}
.mGrid th { 
    padding: 4px 2px; 
    color: #fff; 
    background: #424242 url(grd_head.png) repeat-x top; 
    border-left: solid 1px #525252; 
    font-size: 0.9em; 
}
.mGrid .alt { background: #fcfcfc url(grd_alt.png) repeat-x top; }
.mGrid .pgr { background: #424242 url(grd_pgr.png) repeat-x top; }
.mGrid .pgr table { margin: 5px 0; }
.mGrid .pgr td { 
    border-width: 0; 
    padding: 0 6px; 
    border-left: solid 1px #666; 
    font-weight: bold; 
    color: #fff; 
    line-height: 12px; 
 }   
.mGrid .pgr a { color: #666; text-decoration: none; }
.mGrid .pgr a:hover { color: #000; text-decoration: none; }

I have used three images for header, alternate rows and pager to create a more appealing look. There images are tiled horizontally using CSS to fit the whole row. You can find the images in the sample website code.

GridView Style Images

Conclusion

Creating custom looks for GridView control is very easy. You can create a completely different look using only a few lines of CSS. You can use the same CSS style for all GridView controls in your project and later if you want to change the look you can do it from one location in your style sheet file.