New Use For Control Adapters 1

Control adapters were much discussed when they came out with asp.net 2.0 but nobody seems to have done anything beyond what was given at http://www.asp.net/cssadapters/ .
We found a useful application that solved another problem and I feel there may be more uses we can put it to. Here is the first one we discovered.


The problem
:
Like most applications, we needed tabs.  JS tabs without iframes would mean keeping all the data on same page. That would have made it complex and data intensive JS tabs would also require a conscious effort so that they degrade gracefully. Another issue was to implement security feature where certain tabs would not be available based on roles of the user.  Maintaining tab selection on postback was another problem.
Iframes are loose and require much more effort to stop them from ruining user experience in some cases with large number of fields and several grids and buttons on a single tab in addition to having some of the problems described above.
Finally we decided that it was best to have separate pages and not use js/iframe based tabs for our purpose.

The Solution:

For a while we used a solution where we created a ul and hide or disabled items as needed.
Later when we were trying to implement a menu adapter for office bar/Ribbon, I realized that it can also be used for generating the tabs as we need.
It would

  1. Make the solution generic.
  2. Integrate with regular .Net security infrastructure
  3. Remove what was essentially a navigation control logic from UI.
The solution was simple enough. We just needed to render appropriate set of ul and li and style them properly.

private void BuildTab(MenuItemCollection TabItem, HtmlTextWriter Writer,string MenuMode)
{
Writer.Write(“<ul class=’tabsubnav’ id=’ulsubnav’>”);
      int i = 0;
      if (TabItem.Count > 0)
      {
            foreach(MenuItem item in TabItem)
            {
                  string classval = “Unselected”;
                  if (MenuMode== “Add” && i != 0)
                        item.Enabled = false;
                  if(HttpContext.Current.Request.RawUrl
.ToString().Contains(item.NavigateUrl
.ToLower()))
                        classval = “selected”;
                  if (HttpContext.Current.Request.
QueryString.Count > 0)
                  {
                      item.NavigateUrl += “?” +
HttpContext.Current.Request.QueryString[0];
                      item.Enabled = true;
                  }
                  Writer.Write(“<li id=’tabBasicInfo’>”);
                       
                  if (item.Enabled == true)
                  {
Writer.Write(“<a href=” + item.NavigateUrl +
” class='” + classval +“‘><b><span>” +
item.Text + “</span></b></a>”);
                  }
                  else
                  {
                        classval = “disabled”;
                        item.NavigateUrl = “javascript:void(0)”;
                        Writer.Write(“<a href=” + item.NavigateUrl
+ ” class='” + classval + “‘><b><span>” +
item.Text + “</span></b></a>”);
                   }
                       
                        Writer.Write(“</li>”);
                        i++;
             }
}
            Writer.Write(“</ul>”);
 }

About done.


As soon as this adapter was added to the browser file, it screwed up the Ribbon. Asp.Net Development does not allow to use multiple adapter for the same control for a given browser configuration or to choose adapter on the fly. We were already using menu adapter for the Ribbon. The solution was simply to inherit and create a new class from the asp.net menu.


public
class Tab : Menu
{
}

No additional code was needed.
Sitemap configuration took care of the security aspect of tabs.

<siteMapNodetitle=“”url=#SchoolTabroles=*>

   <siteMapNodeurl=~/School.aspxtitle=School roles=Access_School />
   <siteMapNodeurl=~/Locations.aspxtitle=Locationroles=Access_Location />
<
siteMapNodeurl=~/Grade.aspxtitle=Graderoles=Access_Grade />
<
siteMapNodeurl=~/Room.aspxtitle=Roomroles=Access_Room” />
</
siteMapNode>

The top level node is just to group the children and is not displayed. Thus we can have multiple tab sets configured in a single sitemap file.