Click here to Skip to main content
15,885,777 members
Articles / Web Development / ASP.NET
Article

how to disable and enable links in side bar of Wizard control and How to create tab Control in ASP.NET 2.0

Rate me:
Please Sign up or sign in to vote.
2.31/5 (6 votes)
14 Nov 2006CPOL3 min read 76.6K   1K   19   8
how to disable and enable links in side bar of Wizard control and How to create tab Control

Introduction

Sample screenshot

In this Article You will learn how to Make your own Tabstrip control or How to mimic Tabstrip using Menu and Multiview control. Also i will Explain How To Make Best use of Wizard control.

IN Wizard control Accesing sidebar Links and Disabling was a big challenge for me. I have explained that in this article. Regarding how to use the control and which events to use when Please see Default2.aspx.cs file

This Article will explain Following :

1) How you can tap all the events of asp.net Wizard control in your real App. I have included the demo project which you can see by opening up Default2.aspx file

2) I have written Cool Tabstrip control using ASp.NET 2.0 . You can use that in your Application. Open ShowServerTabs.aspx file and you should be able to see the Custom tabstrip control in action

Here is the code for that :

C#
using System;

using System.Collections;

using System.Web.UI;

using System.Web.UI.WebControls;

namespace myControls

{

[ControlBuilder(typeof(ServerTabsBuilder))]

[ParseChildren(false)]

public class ServerTabs : WebControl, IPostBackEventHandler

{

public int SelectedTabIndex

{

get

{

if (ViewState["SelectedTabIndex"] == null)

return 0;

else

return (int)ViewState["SelectedTabIndex"];

}

set

{

ViewState["SelectedTabIndex"] = value;

}

}

protected override void RenderContents(HtmlTextWriter writer)

{

for (int i = 0; i < this.Controls.Count; i++)

{

ServerTab tab = (ServerTab)this.Controls[i];

string eRef = Page.ClientScript.GetPostBackClientHyperlink(this, i.ToString());

if (SelectedTabIndex == i)

writer.AddAttribute(HtmlTextWriterAttribute.Class, "navigation navigation1");

else

writer.AddAttribute(HtmlTextWriterAttribute.Class, "navigation");

writer.RenderBeginTag(HtmlTextWriterTag.Div);

writer.AddAttribute(HtmlTextWriterAttribute.Href, eRef);

writer.RenderBeginTag(HtmlTextWriterTag.A);

writer.Write(tab.Text);

writer.RenderEndTag(); // A

writer.RenderEndTag(); // Tab DIV

}

writer.Write("<br style='clear:both' />");

writer.AddAttribute(HtmlTextWriterAttribute.Class, "tabContents");

writer.RenderBeginTag(HtmlTextWriterTag.Div);

this.Controls[SelectedTabIndex].RenderControl(writer);

writer.RenderEndTag(); // Tab Contents DIV

}

protected override void AddParsedSubObject(object obj)

{

if (obj is ServerTab)

base.AddParsedSubObject(obj);

}

protected override HtmlTextWriterTag TagKey

{

get

{

return HtmlTextWriterTag.Div;

}

}

public void RaisePostBackEvent(string eventArgument)

{

SelectedTabIndex = Int32.Parse(eventArgument);

}

}

public class ServerTabsBuilder : ControlBuilder

{

public override Type GetChildControlType(string tagName, IDictionary attribs)

{

if (String.Compare(tagName, "tab", true) == 0)

return typeof(ServerTab);

else

return null;

}

}

public class ServerTab : Control

{

private string _Text;

public string Text

{

get { return _Text; }

set { _Text = value; }

}

}

}

Best thing about this control is that it uses div instead of tables and applying stylesheet on this is easy. There is another way of creating Tabstrip control by Using Menu and Multiview control. That way you don't loose the flexibility of what menu and Multiview provides in terms of events and databinding. I will explain that next.

Here is the sample stylesheet i have used for this

.navigation 

{

float:left;

position:relative;

top:1px;

color: #000; 

background-image:none;

text-decoration: none;

} 

.navigation a

{

color: #fff;

text-decoration:none;

background-image:none;

background: #ffa20c url(left-tab.gif) left top no-repeat ;

padding-left:10px;

margin-left:5px;

float:left;

}

.navigation a:hover {

color: #fff;

background-image:none;

text-decoration:none;

background: #781351 url(left-tab-hover.gif) left top no-repeat;

overflow:inherit

} 

.navigation1

{

float:left;

position:relative;

top:1px;

background-image:none;

text-decoration: none;

color: #fff;

} 

.navigation1 a

{

float:left;

text-decoration:none;

background: #781351 url(left-tab-hover.gif) left top no-repeat;

padding-left:10px;

margin-left:5px;

}

.navigation2

{

color: #0ff;

background: #000 ;

padding-left:10px

}

Now here is the sample aspx file using that control

ASP.NET
<%@ Register TagPrefix="custom" Namespace="myControls" %>

<custom:ServerTabs

ID="ServerTabs1"

Runat="Server">

<tab Text="First Tab">

Contents of the first tab

</tab> 

<tab Text="Second Tab">

Contents of the second tab

</tab> 

<tab Text="Third Tab">

Contents of the third tab

</tab> 

<tab Text="Fourth Tab">

<ver1:ver ID="verinder" runat="server" />

</tab> 

</custom:ServerTabs>

3) I have also created tabstrip like interface using multiview and MEnu Control. I have also used Control adapters to convert menu COntrol to show Output in UL and LI html tags instead of Table tags. This will help you to style the control more properly. You can see that control in action by looking at the code in webusercontrol2.aspx

Here is the ASPX file for that...

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl2.ascx.cs"
    Inherits="WebUserControl2" %>

<script runat="server">

protected void menuTabs_MenuItemClick(object sender, MenuEventArgs e)

{

multiTabs.ActiveViewIndex = Int32.Parse(menuTabs1.SelectedValue);

}

</script>

<div>

<asp:Menu

id="menuTabs1" 

CssSelectorClass="PrettyMenu"

StaticMenuItemStyle-CssClass="navigation"

StaticHoverStyle-CssClass="navigation1"

StaticSelectedStyle-CssClass="navigation1"

Orientation="Horizontal"

OnMenuItemClick="menuTabs_MenuItemClick"

Runat="server" Visible="true">

<Items>

<asp:MenuItem

Text="Tab 1"

Value="0" 

Selected="true" >

</asp:MenuItem>

<asp:MenuItem

Text="Tab 2" 

Value="1"/>

<asp:MenuItem

Text="Tab 3"

Value="2" />

</Items>

</asp:Menu> 

</div> 

<br style="float:left" />

<div class="tabBody">

<asp:MultiView

id="multiTabs"

ActiveViewIndex="0"

Runat="server">

<asp:View ID="view1" runat="server">

Contents of first tab

<asp:TextBox ID="FirstName" runat="Server" Text="Enter Your FirstName Here"></asp:TextBox>

</asp:View>

<asp:View ID="view2" runat="server">

Contents of second tab

<asp:TextBox ID="LastName" runat="Server" Text="Enter Your LastName Here"></asp:TextBox>

<div>

<asp:CheckBox ID="SkipBenificiary" runat="server" Checked="false"
    Text="Skip Beneficiary" />

<asp:CheckBox ID="AddBenificiaryAsTwoSteps" runat="server" Checked="false"
    Text="Make Benificiary as Two steps" />

<asp:CheckBox ID="OverrideTheDefaultBeneView" runat="server" Checked="false"
    Text="Load Different Bene View" />

</div>

</asp:View>

<asp:View ID="view3" runat="server">

<asp:PlaceHolder ID="PlaceHolder" runat="server" Visible="true">

<asp:TextBox ID="MiddleName" runat="Server" 
    Text="Enter Your MiddleName Here"></asp:TextBox>

<Dynamic:Ctrl ID="DynamicallyLoaded" runat="server" />

</asp:PlaceHolder>

</asp:View>

</asp:MultiView> 

</div>

In the Above code I am switching views betten Tabs with following code

<

script runat="server">

{

multiTabs.ActiveViewIndex =

}

protected void menuTabs_MenuItemClick(object sender, MenuEventArgs e)Int32.Parse(menuTabs1.SelectedValue);

4) I have added code in Default2.aspx.cs to show how you can access The buttons in sidebar of Wizard control and enable and disable it the way U want. By default Wizard control shows all buttons or lins in sidebar enabled all the time. If you are implimenting a commit as you go model then you need to disable the links as you move forward and allow navigation control. This code I have not seen in other places.

Here is the ASPX file for that

ASP.NET
<asp:Wizard ID="Wizard1" runat="server" ActiveStepIndex="0" 
    BorderColor="#FFDFAD" BackColor="#FFFBD6" BorderWidth="1px"
    Font-Names="Verdana" Font-Size="0.8em" >

<SideBarTemplate><asp:datalist id="SideBarList" runat="server" RepeatDirection="Vertical"
    RepeatLayout="Table" ItemStyle-VerticalAlign="Top">

<ItemStyle Width="15px" />

<itemtemplate>

<asp:Button ID="SideBarButton" BackColor="#FFFBD6" runat="Server" Width="200px"
    style="float:left" />

</itemtemplate>

</asp:datalist>

</SideBarTemplate>

<HeaderTemplate>Header Text for this step goes here</HeaderTemplate>

<WizardSteps>

<asp:WizardStep ID="WizardStep1" runat="server" Title="Review Personal Data" >

<ver1:ver ID="verinder" runat="server" SetActiveTab="0"/>

</asp:WizardStep>

<asp:WizardStep ID="WizardStep2" runat="server" Title="Review Dependent Data">

<ver1:ver ID="ver2" runat="server" SetActiveTab="1" />

</asp:WizardStep>

<asp:TemplatedWizardStep ID="WizardStep3" runat="server"
     Title="Review Benificiary" StepType="Finish">

<ContentTemplate>

My Custom control goes here

</ContentTemplate>

</asp:TemplatedWizardStep>

<asp:TemplatedWizardStep ID="WizardStep4" runat="server" Title="Summary"
    StepType="Complete">

<ContentTemplate>

My Custom control goes here again!

</ContentTemplate>

</asp:TemplatedWizardStep>

</WizardSteps>

<SideBarStyle BackColor="#990000" Font-Size="0.9em" VerticalAlign="Top" />

<NavigationButtonStyle BackColor="White" BorderColor="#CC9966" BorderStyle="Solid"

BorderWidth="1px" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#990000" />

<HeaderStyle BackColor="#FFCC66" BorderColor="#FFFBD6" BorderStyle="Solid"
    BorderWidth="2px"

Font-Bold="True" Font-Size="0.9em" ForeColor="#333333" HorizontalAlign="Center" />

</asp:Wizard>

Here is the CodeBehind File default2.aspx.cs

C#
using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

public partial class Default2 : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

Wizard1.NextButtonClick += new WizardNavigationEventHandler(Wizard1_NextButtonClick);

Wizard1.PreviousButtonClick += new WizardNavigationEventHandler(
    Wizard1_PreviousButtonClick);

Wizard1.SideBarButtonClick += new WizardNavigationEventHandler(
    Wizard1_SideBarButtonClick);

Wizard1.ActiveStepChanged += new EventHandler(Wizard1_ActiveStepChanged);

Control lst1 = (Control)Wizard1.FindControl("SideBarContainer");

DataList lst = (DataList)lst1.FindControl("SideBarList");

lst.ItemCreated += new DataListItemEventHandler(lst_ItemCreated);

lst.ItemDataBound += new DataListItemEventHandler(lst_ItemDataBound);

}

void lst_ItemDataBound(object sender, DataListItemEventArgs e)

{

if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == 
    ListItemType.AlternatingItem)

{

}

}

void lst_ItemCreated(object sender, DataListItemEventArgs e)

{

if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType ==
    ListItemType.AlternatingItem)

{

Button button = (Button)e.Item.FindControl("SideBarButton");

Hashtable hash=GetSideBarButtons();

switch (Wizard1.ActiveStepIndex)

{

case 0:



break;

case 1:

if (hash.ContainsKey("Review Personal Data"))

{

Button btn1 = (Button)hash["Review Personal Data"];

if (btn1 != null)

{

btn1.Enabled = true;

}

}

break;

case 2:

if (hash.ContainsKey("Review Dependent Data"))

{

Button btn1 = (Button)hash["Review Dependent Data"];

if (btn1 != null)

{

btn1.Enabled = true;

}

}

break;

case 3:

if (hash.ContainsKey("Review Benificiary"))

{

Button btn1 = (Button)hash["Review Benificiary"];

if (btn1 != null)

{

btn1.Enabled = true;

}

}

break;

case 4:

break;

}

button.Enabled = false;

}

}

void Wizard1_DataBinding(object sender, EventArgs e)

{

Hashtable buttonList = GetSideBarButtons();

foreach (string btnTxt in buttonList.Keys)

{

if (btnTxt == "Review Personal Data")

{

Button btn = (Button)buttonList<btntxt />;

btn.Enabled = true;

}

else

{

Button btn = (Button)buttonList<btntxt />;

btn.Visible = false;

//btn.CssClass=

}

Wizard1.DisplaySideBar = true;//();

}

}

void Wizard1_ActiveStepChanged(object sender, EventArgs e)

{

WizardStepBase step = Wizard1.ActiveStep;

if (step.ID == "WizardStep1")

{

}

else if (step.ID == "WizardStep2")

{

}

else if (step.ID == "WizardStep3")

{

}

}

private Hashtable GetSideBarButtons()

{

Hashtable buttonsColl = new Hashtable();

Control lst1 = (Control)Wizard1.FindControl("SideBarContainer");

DataList lst = (DataList)lst1.FindControl("SideBarList");

foreach (DataListItem ctrl in lst.Items)

{

Button button = (Button)ctrl.FindControl("SideBarButton");

buttonsColl.Add(button.Text, button);

}

return buttonsColl;

}

void Wizard1_SideBarButtonClick(object sender, WizardNavigationEventArgs e)

{

if (e.NextStepIndex == (e.CurrentStepIndex + 1))

{

e.Cancel = false;

}

else if (e.NextStepIndex < (e.CurrentStepIndex))

{

e.Cancel = false;

}

else if (e.NextStepIndex == e.CurrentStepIndex)

{

e.Cancel = false;

}

else

e.Cancel = true;

}

void Wizard1_PreviousButtonClick(object sender, WizardNavigationEventArgs e)

{

}

protected override void LoadViewState(object savedState)

{

base.LoadViewState(savedState);

string str=(string)ViewState["NewWizardStep"];

if (str == "1")

{

//CreateNewWizardStep();

Wizard1.WizardSteps.Insert(3, this.CreateNewWizardStep());

}

else

{

}

}

private WizardStep CreateNewWizardStep()

{

WizardStep step= new WizardStep();

step.AllowReturn=true;

step.Title = "New Bene Step Added";

step.StepType= WizardStepType.Finish;

WebUserControl2 ctrl=LoadControl("~/controls/WebUserControl2.ascx") as WebUserControl2;

ctrl.ID="MyNewBenificiary";

ctrl.SetActiveTab="2";

ctrl.Visible=true;

Wizard1.WizardSteps[2].StepType = WizardStepType.Step;

step.Controls.Add(ctrl);

return step;

}

void Wizard1_NextButtonClick(object sender, WizardNavigationEventArgs e)

{

if (e.NextStepIndex == 2 && e.CurrentStepIndex == 1)

{

WebUserControl2 control2 = Wizard1.FindControl("ver2") as WebUserControl2;

TextBox lastName = (TextBox)control2.FindControl("LastName");

CheckBox skipBenificiary = (CheckBox)control2.FindControl("SkipBenificiary");

CheckBox addNewStepDynamically = (CheckBox)control2.FindControl(
    "AddBenificiaryAsTwoSteps");

CheckBox LoadDifferentBeneView = (CheckBox)control2.FindControl(
    "OverrideTheDefaultBeneView");

ViewState["NewWizardStep"] = "0";

ViewState["StepDeleted"] = "0";

ViewState["StepThatHasBeenDeleted"]=null;

if (skipBenificiary.Checked == true)

{

//ViewState["StepThatHasBeenDeleted"]=Wizard1.WizardSteps[2];

Wizard1.WizardSteps.Remove(Wizard1.WizardSteps[2]);

ViewState["StepDeleted"] = "1";

}

else if(addNewStepDynamically.Checked==true)

{

ViewState["NewWizardStep"] = "1";

Wizard1.WizardSteps.Insert(3, this.CreateNewWizardStep());

}

else if (LoadDifferentBeneView.Checked == true)

{

//WizardStepBase stepBase = Wizard1.WizardSteps[Wizard1.WizardSteps[2]];

//stepBase.Controls.Remove(

}

if (skipBenificiary.Checked == false)

{

ViewState["StepDeleted"] = "1";

string str=(string)ViewState["StepDeleted"];

if (str == "1")// this means step was deleted

{

//Wizard1.WizardSteps.AddAt(2, (WizardStepBase)ViewState["StepThatHasBeenDeleted"]);

ViewState["StepDeleted"] = 0;

}

}

else 

if (addNewStepDynamically.Checked == false)

{

string str=(string)ViewState["NewWizardStep"];

if (str == "1")

{

Wizard1.WizardSteps.Remove(Wizard1.WizardSteps[3]);

Wizard1.WizardSteps[2].StepType = WizardStepType.Finish;

ViewState["NewWizardStep"] = "0";

// means we have to remove that step

}

}

}

}

}

My First challenge was how to get to the buttons in sideBar :

Here is the code for that

private Hashtable GetSideBarButtons()Hashtable buttonsColl = new Hashtable();Control lst1 = (Control)Wizard1.FindControl("SideBarContainer");DataList lst = (DataList)lst1.FindControl("SideBarList");foreach (DataListItem ctrl in lst.Items)Button button = (Button)ctrl.FindControl("SideBarButton");return buttonsColl;

{

{

buttonsColl.Add(button.Text, button);

}

}

DataList in SideBar is inside SideBarContainer Which is undocumented and this is how you can rech to buttons

Also Now Next challenge for me was to How to Change this button to Gray(disable it). Doing it in PageLoad doesn't work because Databinding of DataList happens after PageLoad :)

So here is the trick i used . In page Load i attach even listener and then enable and disable control from that listner:

Control lst1 = (Control)Wizard1.FindControl("SideBarContainer");DataList lst = (DataList)lst1.FindControl("SideBarList");new DataListItemEventHandler(lst_ItemCreated);new DataListItemEventHandler(lst_ItemDataBound);

lst.ItemCreated +=

lst.ItemDataBound +=

In the Items Created event Handler i actually enable or disable the buttons.

4) My Next Job was how to Move The Wizard Navigation bar To top . This is Tough . I need to write Control Adapter for that. I will updae this article when i have solution.

5) Microsoft has released control Adapters which you can attach to control to render Different HTML for same Control. This is helpful for lot of controls which emit Table instead of div. Having Div Helps in styling the control. Using control adaptyer is easy. Just google it to see microsoft white paper.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCan't disable Finish button Pin
letsgetsilly17-Apr-07 5:54
letsgetsilly17-Apr-07 5:54 
GeneralRe: You're making this harder on yourself than need be Pin
verinder_bindra16-Nov-06 13:22
verinder_bindra16-Nov-06 13:22 
GeneralRe: You're making this harder on yourself than need be Pin
verinder_bindra16-Nov-06 13:26
verinder_bindra16-Nov-06 13:26 
How will you enable disable links using this solution. You have to write custom logic for that. One situation is if steps are generated dynamically then top navigation bar should enable or disable links properly? How will you do that with your approch? I think combination of my logic for enabling disabling links and Control adapter will give full control on navigation. PLease do tell me your idea on that?

Verinder

none

GeneralRe: You're making this harder on yourself than need be Pin
Kevin C Ferron16-Nov-06 14:02
Kevin C Ferron16-Nov-06 14:02 
GeneralRe: You're making this harder on yourself than need be Pin
Kevin C Ferron16-Nov-06 17:15
Kevin C Ferron16-Nov-06 17:15 
GeneralRe: You're making this harder on yourself than need be Pin
YanDav9-Jan-07 8:55
YanDav9-Jan-07 8:55 
GeneralRe: You're making this harder on yourself than need be Pin
verinder_bindra26-Jan-07 7:49
verinder_bindra26-Jan-07 7:49 
NewsYou're making this harder on yourself than need be Pin
Kevin C Ferron15-Nov-06 10:48
Kevin C Ferron15-Nov-06 10:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.