If you plan to follow along step by step with this chapter, we recommend following some naming conventions to make compiling and debugging easier. As always, both C# and Visual Basic .NET code will be provided for this project.
You’ll start by creating the project. First, create a standard ASP.NET application in the language of your choice. Name it either Chapter9CS for C# or Chapter9VB for Visual Basic .NET. Next, right-click the project name in the Solution window and choose Add and then New Component. In the dialog box that appears, choose Web Custom Control and name this component SimpleTabControl.cs or SimpleTabControl.vb, depending on the language you have chosen for this example.
Now you can start coding the basic tab control framework. First, you will create the very basic input and output routines of the tab control. Listing 9.1 contains the C# version of the code, while Listing 9.2 contains the Visual Basic .NET version. Listings 9.3 and 9.4 contain the code of one of the ASP.NET pages that you will be using to test the control for the C# and Visual Basic .NET projects, respectively. Finally, Listing 9.5 is a listing of the code-behind file that will be used for the C# ASP.NET pages, and Listing 9.6 contains the same code in Visual Basic .NET. You will want to create three separate ASP.NET pages, each with the same code. The only difference between the pages is having the proper code-behind file referenced from each page, as well as having each code-behind file with a unique class in it. This will be explained a bit more as we explain the example in the pages ahead.
using System; using System.Web.UI; namespace Chapter9CS { public class SimpleTabControl : System.Web.UI.WebControls.WebControl, IPostBackEventHandler { private string[] aPages; private string[] aNames; public string CurPage { get { return (string)ViewState["curPage"]; } set { ViewState["curPage"] = value; } } public string Names { get { return (string)ViewState["names"]; } set { ViewState["names"] = value; aNames = value.Split("∼"); ViewState["aNames"] = aNames; } } public string Pages { get { return (string)ViewState["pages"]; } set { ViewState["pages"] = value; aPages = value.Split("∼"); ViewState["aPages"] = aPages; } } public string ActiveColor { get { return (string)ViewState["activeColor"]; } set { ViewState["activeColor"] = value; } } public string InactiveColor { get { return (string)ViewState["inactiveColor"]; } set { ViewState["inactiveColor"] = value; } } public string RedirPage { get { return (string)ViewState["redirPage"]; } set { ViewState["redirPage"] = value; } } public void RaisePostBackEvent(string eventArgument) { ViewState["curPage"] = eventArgument; ViewState["redirPage"] = aPages[Convert. ToInt32(eventArgument)]; } // Override for outputting text to the browser protected override void Render(HtmlTextWriter output) { int i; if (aPages.GetUpperBound(0) != aNames.GetUpperBound(0)) { // toss the error here } else { output.Write("<table width='100%' border><tr>"); for (i = 0; <= aNames.GetUpperBound(0); i++) { output.Write("<td bgcolor=""); if (i. ToString() == (string)ViewState["curPage"]) output.Write(ViewState["activeColor"]); else output.Write(ViewState["inactiveColor"]); output.Write(""><a id="" + aPages[i] + "" href="javascript:" + Page.GetPostBackEventReference(this, i. ToString()) + "">" + aNames[i] + "</td> "); } output.Write("</tr></table>"); } } } } |
Imports System.ComponentModel Imports System.Web.UI Public Class SimpleTabControl Inherits System.Web.UI.WebControls.WebControl Implements IPostBackEventHandler Dim aPages() As String Dim aNames() As String Property CurPage() As String Get CurPage = ViewState("curPage") End Get Set(ByVal Value As String) ViewState("curPage")= Value End Set End Property Property Names() As String Get Names = ViewState("names") End Get Set(ByVal Value As String) ViewState("names") = Value aNames = Value.Split("∼") ViewState("aNames") = aNames End Set End Property Property Pages() As String Get Pages = ViewState("Pages") End Get Set(ByVal Value As String) ViewState("pages") = Value aPages = Value.Split("∼") ViewState("aPages") = aPages End Set End Property Property ActiveColor() As String Get ActiveColor = ViewState("activeColor") End Get Set(ByVal Value As String) ViewState("activeColor") = Value End Set End Property Property InactiveColor() As String Get InactiveColor = ViewState("inactiveColor") End Get Set(ByVal Value As String) ViewState("inactiveColor") = Value End Set End Property Property RedirPage() As String Get RedirPage = ViewState("redirPage") End Get Set(ByVal Value As String) ViewState("redirPage") = Value End Set End Property Sub RaisePostBackEvent(ByVal eventArgument As String) Implements IPostBackEventHandler .RaisePostBackEvent ViewState("curPage") = eventArgument ViewState("redirPage") = aPages(Convert. ToInt32(eventArgument)) End Sub Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter) Dim i As Integer If aNames.GetUpperBound(0) <> aPages.GetUpperBound(0) Then 'error Else output.Write("<table width='100%' border><tr>") For i = 0 To aNames.GetUpperBound(0) output.Write("<td bgColor='") If i. ToString() = ViewState("curPage") Then output.Write(ViewState("activeColor")) Else output.Write(ViewState("inactiveColor")) End If output.Write("'><a id='" & aPages(i) & "' href=""javascript:" & Page .GetPostBackEventReference(Me, i. ToString()) + """>" & aNames(i) & "</td>" & vbCrLf) Next output.Write("</tr></table>) End If End Sub End Class |
<%@ Register TagPrefix="Tab" Namespace="Chapter9CS" Assembly = "Chapter9CS" %> <%@ Page language="c#" Codebehind="Page1.aspx.cs" AutoEventWireup="false" Inherits="Chapter9CS.Page1" %> <!DOCTYPE HTML PUBLIC "-/ /W3C/ /DTD HTML 4.0 Transitional/ /EN"> <HTML> <HEAD> <title>Chapter 9 - C#</title> </HEAD> <body> <form id="Form1" method="post" runat="server"> <Tab:SimpleTabControl pages="page1.aspx∼page2.aspx∼page3.aspx" names="Page 1∼Page 2∼Page 3" activeColor="#ff0000" inactiveColor="#0000ff" name="tab" id="tab" runat="server"/> </form> This is PAGE 1. </body> </HTML> |
<%@ Register TagPrefix="Tab" Namespace="Chapter9Visual Basic" Assembly = "Chapter9Visual Basic" %> <%@ Page language="vb" Codebehind="Page1.aspx.vb" AutoEventWireup="false" Inherits="Chapter9Visual Basic.Page1" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>Chapter 9 - Visual Basic</title> </HEAD> <body> <form id="Form1" method="post" runat="server"> <Tab:SimpleTabControl pages="page1.aspx∼page2.aspx∼page3.aspx" names="Page 1∼Page 2∼Page 3" activeColor="#ff0000" inactiveColor="#0000ff" name="tab" id="tab" runat="server"/> </form> This is PAGE 1. </body> </HTML> |
using System; namespace Chapter9CS { public class Page1 : System.Web.UI.Page { protected Chapter9CS.SimpleTabControl tab; public Page1() { Page.Init += new System.EventHandler(Page_Init); } private void Page_Load(object sender, System.EventArgs e) { if(IsPostBack) tab.CurPage = Request.QueryString.Get("curpage"); else tab.CurPage = "0"; } private void Page_Init(object sender, EventArgs e) { InitializeComponent(); } private void InitializeComponent() { this.Load += new ystem.EventHandler(this.Page_Load); this.PreRender += new System.EventHandler(this.Page_PreRender); } private void Page_PreRender(object sender, System.EventArgs e) { if (IsPostBack) Response.Redirect(tab.RedirPage + "?curpage=" + tab.CurPage ); } } } |
Public Class Page1 Inherits System.Web.UI.Page Protected tab As Chapter9Visual Basic.SimpleTabControl Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load If IsPostBack Then tab.CurPage = Request.QueryString.Get("curpage") Else tab.CurPage = "0" End If End Sub Private Sub Page_PreRender(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.PreRender If IsPostBack Then Response.Redirect(tab.RedirPage & "?curpage=" & tab.CurPage) End If End Sub End Class |
Every server control must inherit from the System.Web.UI.WebControls. Control namespace. Ours is no different. You will also notice several properties that we have created. These properties become attributes that can be set in the ASP.NET page after the control has been put in place. For example, the standard HTML text box has an attribute named value that can be used to set the default text that appears in the text box when the page is loaded.
In the tab control are several properties: Pages, Names, ActiveColor, InactiveColor, CurPage, and RedirPage. Pages will contain a delimited list of ASP.NET pages that each tab will take the browser to. The Names property contains a delimited list of the name to display to the user. ActiveColor and InactiveColor store the background colors of the active and inactive tabs, respectively. Finally, the CurPage and RedirPage properties keep track of the current page and the page to move to based on which tab the user clicked. All these properties are stored in the ViewState dictionary, which provides a way to store state information between page requests of the same page, but only through form submissions.
In the namespace inherited from System.Web.UI.WebControls.Control, you need to override the Render method. This is the function that sends the output down to the browser. Typically, this is where you will output your HTML. In this function, you render a table with the links provided in the Pages and Names properties specified in the HTML tag.
The other thing to notice is that the RaisePostBackEvent method is implemented from the IPostBackEventHandler interface. This is done so that you can create clickable links that generate form submissions instead of just regular links. This method is called whenever one of these special links is clicked; it enables you to handle the click in a special way. In this example, you’re simply grabbing the special parameter on your links : the index into the Page array that you will be redirecting to.
Now take a look at the ASP .NET page. To use the server control on the page, it is necessary to add the Register directive at the top of the page and specify what the tag name will be (Tab), what the namespace is (Chapter9VB or Chapter9CS) and, finally, the assembly that it is located inside (Chapter9VB or Chapter9CS).
With that directive in place, you can reference the server control using the following syntax:
<tab:SimpleTabControl/>
That creates an instance of the example tab control. Looking at the full page listed earlier, you will notice that the properties are specified on the tab control as HTML attributes. In the example, you have the attributes shown in Table 9.1.
Tag Attribute | Value |
---|---|
Pages | page1.aspx∼page2.aspx∼page3.aspx |
Names | Page 1∼Page 2∼Page 3 |
activeColor | #ff0000 |
inactiveColor | #0000ff |
Both Pages and Names contain a ∼ –delimited list of parameters. They must match in length of elements. Pages contains the pages to redirect to when the Name link is clicked.When writing this example, be sure to create ASP.NET pages named page1.aspx, page2.aspx, and page3.aspx. All three will have their own code-behind files and will contain the same code across all three pages, except for the name of the class contained in the Chapter9XX namespace. For example, Page1.aspx would contain a Page1 class, while Page2.aspx would contain a Page2 class.
That should be enough background information to understand the example. A detailed discussion of server-side controls is really outside the scope of this book, but a general understanding is required so that you can understand the example provided.