Setting ActiveStepindex on a Wizard Control

Last post 02-17-2009 2:47 PM by gogginl. 7 replies.

Sort Posts:

  • Setting ActiveStepindex on a Wizard Control

    03-18-2006, 12:34 PM
    • Member
      40 point Member
    • Matt Wynne
    • Member since 03-18-2006, 8:39 AM
    • Posts 8
    I'm using a 2.0 Wizard control which I want my users to be able to jump into from another page using hyperlinks to determine which step to start at.

    I've tried setting the ActiveStepIndex in Page.OnLoad but I'm getting some quite unexpected behaviour from the Wizard control in terms of the events that subsequently fire, and I find that the Wizard won't let me move any further back from the step I initially set the ActiveStepIndex to.

    Has anyone experienced this too, and do they have a workaround? It seems a little quirky, but it might be me misunderstanding how to use the ActiveStepIndex property properly.

    The following simple example illustrates what I'm talking about. Try putting trace messages on the WizardStep.Activate/Deactivate events and you'll see some funky stuff going on. Note that if you use the sidebar to go back beyond the 'jumped-to' step, the wizard seems to be freed up again...

    <%@ Page Language="C#" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <script runat="server">
        protected override void OnInit(EventArgs e)
        {
            // only check on first time in
            if (!IsPostBack)
                // look in querystring for jump command
                if (Request.QueryString["jumptostep"] != null)
                    // do the jump
                    TheWizard.ActiveStepIndex = Convert.ToInt32(Request.QueryString["jumptostep"]);
        }
    </script>
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head><title /></head>
        <body>
            <form id="form1" runat="server">
                imagine these links are on another page:<br />
                jump in at: [<a href="?jumptostep=1">step 1</a>][<a href="?jumptostep=2">step 2</a>]
                <hr />
                <asp:Wizard ID="TheWizard" runat="server">
                    <WizardSteps>
                        <asp:WizardStep ID="Step0" runat="server">Step 0</asp:WizardStep>
                        <asp:WizardStep ID="Step1" runat="server">Step 1</asp:WizardStep>
                        <asp:WizardStep ID="Step2" runat="server">Step 2</asp:WizardStep>
                    </WizardSteps>
                </asp:Wizard>
            </form>
        </body>
    </html>

    Can anyone shed any light as to what's going on? This has been driving me barmy all of Friday and it's going to spoil my weekend at this rate!Confused <img src="/>

    cheers,
    Matt
  • Re: Setting ActiveStepindex on a Wizard Control

    03-18-2006, 2:58 PM
    • Member
      40 point Member
    • Matt Wynne
    • Member since 03-18-2006, 8:39 AM
    • Posts 8
    Taking a break and coming back to this with a clear head, I think i have fixed it. The answer is actually ridiculously easy. The problems manifest themselves when you try to nagivate forwards and backwards after jumping in - strange things happen with the e.NextStepIndex value if you watch the next/prev button events fired - so the solution is to just hook the NextButtonClick and PreviousButtonClick events on the Wizard, and override the screwy e.NextStepindex settings by deliberately setting the ActiveStepIndex each time.

        void TheWizard_PreviousButtonClick(object sender, WizardNavigationEventArgs e)
        {
            ((Wizard)sender).ActiveStepIndex = ((Wizard)sender).ActiveStepIndex - 1;
        }
       
        void TheWizard_NextButtonClick(object sender, WizardNavigationEventArgs e)
        {
            ((Wizard)sender).ActiveStepIndex = ((Wizard)sender).ActiveStepIndex + 1;
        }


    You get an ActiveStepChanged event firing when you make those changes to ActiveStepIndex, but that's expected and fine by me.

    This seems to work for me, though I can't understand why this wouldn't be what's going on inside the control anyway. I guess either I'm misunderstanding how it's supposed to work, or this is a bug.

    Hope this helps someone else.

    cheers,
    Matt
  • Test code

    03-18-2006, 3:05 PM
    • Member
      40 point Member
    • Matt Wynne
    • Member since 03-18-2006, 8:39 AM
    • Posts 8
    by the way, if anyone's interested, here's the test rig I used to figure this out, it's a modified version of the code I posted above:

    <%@ Page Language="C#" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <script runat="server">
        protected override void OnLoad(EventArgs e)
        {
            TheWizard.ActiveStepChanged += new EventHandler(TheWizard_ActiveStepChanged);
            TheWizard.NextButtonClick += new WizardNavigationEventHandler(TheWizard_NextButtonClick);
            TheWizard.PreviousButtonClick += new WizardNavigationEventHandler(TheWizard_PreviousButtonClick);
            TheWizard.Init += new EventHandler(TheWizard_Init);
            TheWizard.Load += new EventHandler(TheWizard_Load);
            TheWizard.PreRender += new EventHandler(TheWizard_PreRender);
            TheWizard.Unload += new EventHandler(TheWizard_Unload);
           
            // only check on first time in
            if (!IsPostBack)
                // look in querystring for jump command
                if (Request.QueryString["jumptostep"] != null)
                {
                    // do the jump
                    //TheWizard.ActiveStepIndex = Convert.ToInt32(Request.QueryString["jumptostep"]);
                    TheWizard.MoveTo(TheWizard.WizardSteps[
                        Convert.ToInt32(Request.QueryString["jumptostep"])
                        ]);
                }
        }

        void TheWizard_Unload(object sender, EventArgs e)
        {
            ReportState(sender, "Unload");
        }

        void TheWizard_PreRender(object sender, EventArgs e)
        {
            ReportState(sender, "PreRender");
        }

        void TheWizard_Load(object sender, EventArgs e)
        {
            ReportState(sender, "Load");
        }

        void TheWizard_Init(object sender, EventArgs e)
        {
            ReportState(sender, "Init");
        }

        void TheWizard_PreviousButtonClick(object sender, WizardNavigationEventArgs e)
        {
            ReportState(sender, "PreviousButtonClick", e.CurrentStepIndex, e.NextStepIndex);
            ((Wizard)sender).ActiveStepIndex = ((Wizard)sender).ActiveStepIndex - 1;
            ReportState(sender, "PreviousButtonClick - Fix?", e.CurrentStepIndex, e.NextStepIndex);
           
        }
       
        void TheWizard_NextButtonClick(object sender, WizardNavigationEventArgs e)
        {
            ReportState(sender, "NextButtonClick", e.CurrentStepIndex, e.NextStepIndex);
            ((Wizard)sender).ActiveStepIndex = ((Wizard)sender).ActiveStepIndex + 1;
            ReportState(sender, "NextButtonClick - Fix?", e.CurrentStepIndex, e.NextStepIndex);
        }

        void TheWizard_ActiveStepChanged(object sender, EventArgs e)
        {
            ReportState(sender, "ActiveStepChanged");
        }
        void ReportState(object sender, string eventName)
        {
            ReportState(sender, eventName, null, null);
        }
        void ReportState(object sender, string eventName, int? currentStepIdx, int? nextStepIdx)
        {
            Wizard wiz = (Wizard)sender;
            WriteTrace("<b>" + eventName + "</b>" +
                "ActiveStepIndex = " + wiz.ActiveStepIndex.ToString() +
                ((currentStepIdx.HasValue) ? "CurrentStepIndex = " + currentStepIdx.ToString() : "") +
                ((nextStepIdx.HasValue) ? "NextStepIndex = " + nextStepIdx.ToString() : "")
                );
        }
       
        void WriteTrace(string msg)
        { this.TraceBox.Text += msg + "<br/>"; }
       
    </script>
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head><title /></head>
        <body>
            <form id="form1" runat="server">
                imagine these links are on another page:<br />
                jump in at: [<a href="?jumptostep=2">step 2</a>][<a href="?jumptostep=3">step 3</a>]
                <hr />
                <asp:Wizard ID="TheWizard" runat="server">
                    <WizardSteps>
                        <asp:WizardStep ID="Step0" runat="server">Step 0</asp:WizardStep>
                        <asp:WizardStep ID="Step1" runat="server">Step 1</asp:WizardStep>
                        <asp:WizardStep ID="Step2" runat="server">Step 2</asp:WizardStep>
                        <asp:WizardStep ID="Step3" runat="server">Step 3</asp:WizardStep>
                        <asp:WizardStep ID="Step4" runat="server">Step 4</asp:WizardStep>
                        <asp:WizardStep ID="Step5" runat="server">Step 5</asp:WizardStep>
                    </WizardSteps>
                </asp:Wizard>
                <asp:Literal ID="TraceBox" runat="server" EnableViewState="false"></asp:Literal>
            </form>
        </body>
    </html>



  • The Plot Thickens

    03-21-2006, 1:07 PM
    • Member
      40 point Member
    • Matt Wynne
    • Member since 03-18-2006, 8:39 AM
    • Posts 8
    Just thought I'd add some more detail to this thread after the weekend so it may get a little more attention. The solution was not quite a simple as I had first thought, and I've had to disable viewstate on the wizard to stop some dynamicly-generated controls I use on one step from failing when the form posts-back after setting ActiveStepIndex.

    My feeling is that the wizard is storing 'current step' state in two different ways (maybe using a hidden field), and the various parts of the control (e.g restoring viewstate) are not all consistently using the same value. If I had time I'd dig a bit deeper, but deadlines call...

    I'd love for someone with more experience of this control than mine to comment... anyone?

  • Re: The Plot Thickens

    03-23-2006, 4:42 PM
    • Contributor
      2,738 point Contributor
    • kashif
    • Member since 06-11-2002, 1:34 PM
    • Posts 547
    • AspNetTeam
      Moderator

    Matt

     

    The wizard is designed to keep a history of steps and use this history for backward navigation [clicking 'Previous' means going to the last step in the history not the 'Previous' step to the current step in the wizard. Thus if a user jumped to a particular step by setting ActiveStepIndex on the first browse  – there is no history and the “Previous” button will not do anything, the side bar has to be used in such a case for navigation. 

     

    Thanks,

    Kashif

  • Re: The Plot Thickens

    03-24-2006, 1:07 AM
    • Member
      40 point Member
    • Matt Wynne
    • Member since 03-18-2006, 8:39 AM
    • Posts 8
    Aha! Thanks Kashif, with that perspective on it things start to make a lot more sense. Any tips on where I can find out that level of information about these new controls? The MSDN documentation is pretty plain, and there's not much on CodeProject etc. yet.

    thanks again,
    Matt
  • Re: The Plot Thickens

    02-03-2009, 12:44 PM
    • Participant
      1,576 point Participant
    • lax4u
    • Member since 05-28-2004, 2:45 PM
    • Posts 852

    then can we programatically add history to Wizard control?

  • Re: The Plot Thickens

    02-17-2009, 2:47 PM
    • Member
      62 point Member
    • gogginl
    • Member since 06-29-2006, 1:49 PM
    • Posts 143

     

    I was able to get the steps to work consistent by adding a handler and for each NEXT / PREVIOUS event either subtract or add to the active index. Some minor conditions were added and validation to also protect consistency. Additionally I included a START step followed by regular steps and Fisihed step. I set the ALLOW PREVIOUS to True on all steps and only changed this setting to False when needed in backend code.

    e.g. 

    ' Handler for Nex/Previous buttoms must be first in LOAD section.

    AddHandler myWizard.PreviousButtonClick, handler

    AddHandler myWizard.NextButtonClick, handler

    Protected Sub myWizard_NextButtonClick(ByVal sender As Object, ByVal e As     System.Web.UI.WebControls.WizardNavigationEventArgs) Handles myWizard.NextButtonClick

    myWizard.ActiveStepIndex = myWizard.ActiveStepIndex + 1

    End Sub 

    Protected Sub myWizard_PreviousButtonClick(ByVal sender As Object, ByVal e As     System.Web.UI.WebControls.WizardNavigationEventArgs) Handles myWizard.PreviousButtonClick

    myWizard.ActiveStepIndex = myWizard.ActiveStepIndex - 1

    End Sub 

Page 1 of 1 (8 items)