# VBForums CodeBank > CodeBank - Visual Basic .NET >  [2008][UPDATE, Aero Glass] Wizard Template UserControl - Full Design-time support!

## NickThissen

Hi,

This is my latest UserControl: a Wizard template with full Design-time support. 

Besides being a very useful control if you ever want to create a Wizard (no longer do you have to mess around with Panels, making them (In)Visible manually whenever you want to add a control...), this is also a very good lesson on Designers, and the use of Smart-Tags etc.


Drop the control onto your form, add pages as you desire and browse through them using the Next/Back buttons (during Design-time!). Change the Title / Description / Icon of every page and simply drag & drop the required controls onto the page, just like in a TabControl!


Here is a description with screenshots:

The main control is the *WizardCtrl* usercontrol. This is the control you drop onto your form. It contains three basic regions:
Header (Title, Description and Icon display)PagesPanel (Hosts all the pages)Navigation panel (Cancel, Back, Next, Finish buttons)

The *PagesPanel* is a simple Panel that will host the *WizardPages*. A *WizardPage* is a usercontrol inheriting from the Panel and can host whichever control you want to put on that page.

When you add the *WizardCtrl* to your form, a new *WizardPage* is automatically added:


As you can see, there is no Header panel (Title/Description). This is because the first page is by default a *Welcome page* and no header is displayed. Change the *IsWelcomePage* property manually if you don't need a Welcome page.

As soon as you add a new page, a normal page is added:


As you can see, the Header panel displays the default Title and Description, and I manually added an Icon. The Icon is invisible when there is no Icon specified.

To add pages, remove pages or select a different page, you can use the *WizardCtrl* Smart Tags:


You can also browse through the pages using the Next/Back buttons, just like you can during Run-time.

To change common properties such as Title, Description and Icon, you can use the *WizardPage* Smart Tags:


Besides the 'Welcome Page' property, there is also the 'Last Page' property. When True, this will change the text of the Next button to Finished (or whatever you have specified as FinishedButtonText).

Finally, there is a small control called *ThreeDLine* that draws a 3d-border line, as can be seen during Run-time:



There are a number of properties you can use to change the appearance of the *WizardCtrl*, such as the NextButtonText, BackButtonText, CancelButtonText and FinishedButtonText (these are self-explanatory I hope).

There are also a number of (also self-explanatory) Events you can use such as the NextButtonClicked, BackButtonClicked, CancelButtonClicked and SelectedIndexChanged events.



Besides the Controls explained above, there are also two *Designers*. The Designers create the Smart-Tags, and more importantly allow the Next and Back buttons to be used during Design-time.

Finally, the Misc.vb file contains two miscellaneous classes, one to take care of type conversion to a WizardPage, and the other to take care of the 'Pages' CollectionEditor.


I have attached an Example project (created in VS2008) for you to use (you may need to Build the solution to get rid of any errors). If you don't have VS2008 you can simply start a new project and add the separate classes manually:
WizardCtrl.vbWizardPage.vbWizardCtrlDesigner.vbWizardPageDesigner.vbMisc.vb


That's about it... If you have any questions, let me know. If you found a bug, let me know. If you have any suggestions, let me know!

----------


## NickThissen

Here is an update (actually a different version), using dom_stapleton's AeroWizard codebank submission to extend the Aero Glass into the client area, making it look exactly like a Windows Vista Wizard. 

It is not an updated version of my control (not yet at least) as you cannot use this control without enabling Aero Glass (so you cannot use it on XP for example). In the future I might make a version of this control where you can just change a property to switch between 'normal' and Aero style.

Other changes from this to the other version include:
- No longer supports "Description".
- No longer supports undocking. Control must always be docked (otherwise, the Aero glass doesn't work properly).

In addition, I used noahssite's Moving a Borderless Form code to allow the user to drag the form via the extended glass 'panel'.

Here's a screenshot of the new version:


The design-time support has not changed, it looks the same as the old version (obviously without Aero Glass).

Sample project is attached!

----------


## stru4nak

Very good tnx

----------


## obi1kenobi

Excellent control  :Smilie:  Btw, may I ask where you found those glassy icons used in the screenshots in your first post?

----------


## NickThissen

> Excellent control  Btw, may I ask where you found those glassy icons used in the screenshots in your first post?


Thanks. I'm sorry, I don't remember! I had them on Vista but I've had to format and go back to XP since then and I didn't back up the icons... I think they came with a large set of Vista like icons or something... I'll see if I can find them again.

----------


## obi1kenobi

Thanks  :Smilie:

----------


## AlexStefan

Hi Nick,

Looks like a nice control.

Question: I want to add some validation on the first page of the wizard. 
So when you press Next, a check will be performed whether data entered on the first page of the wizard is valid.
If it is not valid then the wizard should not go to the second page.
How can I prevent the wizard from going to the second page?

Kind regards,
Alex

----------


## NickThissen

> Hi Nick,
> 
> Looks like a nice control.
> 
> Question: I want to add some validation on the first page of the wizard. 
> So when you press Next, a check will be performed whether data entered on the first page of the wizard is valid.
> If it is not valid then the wizard should not go to the second page.
> How can I prevent the wizard from going to the second page?
> 
> ...


At the moment unfortunately, you can not. However, it is not very hard to implement that yourself. I will give you a brief outline of how to do it now, but if you can't get it just tell me and I will try it myself and update this control.

The idea is to let the control throw a 'BeforeNextButtonClicked' event which is fired _before_ the actions usually performed in the NextButtonClicked event are executed. 
I don't have access to Visual Studio right now so I don't remember the exact code, but the NextButtonClicked event (in the WizardCtrl source, not on your form!) should look something like this:

vb.net Code:
Private Sub NextButton_Clicked(ByVal sender As Object, ByVal e As EventArgs) Handles NextButton.Clicked
   'Some code here to go to the next page
   '...
    'Raise external 'NextButtonClicked' event:
   RaiseEvent NextButtonClicked
End Sub

The general idea now is to raise another event (BeforeNextButtonClicked) before the code to go to the next page. With this event, you pass an argument 'cancel'.
The user (you) can then write his code in that event (outside of the source control) and set the 'cancel' argument of the event to True to cancel the event.

If you don't understand this, have a look at the FormClosing event of any Windows Form. It carries a ClosingEventArgs parameter (e) that has a 'Cancel' property. If you set that to true, the event is canceled and the form will not close.

Something like this maybe:

vb.net Code:
Public Event BeforeNextButtonClicked(ByRef cancel As Boolean)
 Private Sub NextButton_Clicked(ByVal sender As Object, ByVal e As EventArgs) Handles NextButton.Clicked
   'Raise external 'BeforeNextButtonClicked' event:
   Dim cancel As Boolean = False
   RaiseEvent BeforeNextButtonClicked(cancel)
    'Check if the user wants to cancel and only continue if he does not
   If cancel = False Then
      'Some code here to go to the next page
      '...
       'Raise external 'NextButtonClicked' event:
      RaiseEvent NextButtonClicked
   End If
End Sub

Note that the event takes the 'cancel' parameter as a reference (ByRef) because it can be changed outside of the current class, and the change must be persisted; the WizardCtrl must know if the user changed the 'cancel' value to True or not!

In your form code (in the WizardCtrl_BeforeNextButtonClicked event) you can then do something like this:

vb.net Code:
Private Sub WizardCtrl1_BeforeNextButtonClicked(ByRef cancel As Boolean) Handles WizardCtrl1.BeforeNextButtonClicked
   'validate the info one current page here:
   If InfoIsValid() = False Then
      cancel = True
   End If
End Sub

If the InfoIsValid() method (which I made up and should be replaced by your validation method) returns False (the info is not valid) then the cancel boolean is set to True and the event is canceled: the wizard does not continue to the next page (and does not raise the NextButtonClicked event either!).


Again if you cannot get this to work just yell and I'll build it in. I think I probably will build it in anyway because it is probably a pretty common feature; I can't believe I missed that out!

----------


## NickThissen

Alright, I have updated the WizardCtrl class. Instead of just a 'cancel' boolean, I decided to use custom Event Arguments that hold a "Cancel" property, and also a "CurrentPage" property that holds the current page.

This way, you can use the *BeforeNextButton_Clicked* event as such:

vb.net Code:
Private Sub WizardCtrl1_BeforeNextButton_Clicked(ByVal sender As System.Object, ByRef e As WizardControlExample.BeforeNextButtonEventArgs) Handles WizardCtrl1.BeforeNextButton_Clicked
        'Check current page
        If e.CurrentPage Is Me.WizardPage3 Then
             'Validate info on current page
            If TextBox1.Text = "Hello World" Then
                e.Cancel = False
            Else
                e.Cancel = True
            End If
        End If
    End Sub
Assuming you have a TextBox1 on WizardPage3, whose text should be "Hello World". If it's text is not "Hello World" the Next button click should be canceled. 


Since I am no longer running Vista, I am getting some problems with missing DLL files in my project on XP. I have never seen them before, but I'll look into them, I want this project to work on XP as well (obviously without Aero Glass). 

This stops me from uploading the entire project however, so I have just attached the new 'WizardCtrl.vb' class. Replace the old 'WizardCtrl.vb' class with this new one. The only changes are the Before___ events. 

In case you have already changed some of the WizardCtrl class and don't want to lose your work, you can open up my new WizardCtrl class and copy/paste the following sections into your custom WizardCtrl class:
- Under the 'Events' region: The 3 "Delegate" subs + the 3 Before___ events (lines 17 to 37).
- The btnNext_Click, btnPrev_Click and btnCancel_Click events are updated; view my changes and modify your own as needed (lines 303 to 336).
- The entire (new) 'Event Handlers' region containing three new classes (lines 597 to 641).


Hope you are satisfied with the changes!

----------


## AlexStefan

Thanks Nick for the effort!

I did run into some other trouble as well though (with the ThreeDLine that would not draw a border), so in the end I wrote my own code.

But it was certainly useful to examine your WizardCtrl class, it increased my knowledge and gave me a couple of ideas for the near future.

Keep up the good work  :Thumb:

----------


## obi1kenobi

Well it certainly would be nice if you could provide the code which fixes those troubles you had... Chances are that someone else will have those same issues...

----------


## NickThissen

I am not aware of any issues with the 3D-line..? It is not my code but it has always worked fine for me. What issues are you talking about? How did you fix them?

----------


## Rickk

Hi,

I just downloaded this an opened it in visual studio 2008.

When i run it i get an empty form. How do i create pages etc? like the screenshots above?

----------


## NickThissen

Did you build the solution? I can only imagine you getting an empty form if you didn't build your solution, which would result in an error screen when you try to open the form, which you ignored by simply clicking continue. Any unknown controls are then removed from the form.

Try building the solution (Build menu) and the WizardCtrl control should appear at the top of the Toolbox.

----------


## Rickk

> Did you build the solution? I can only imagine you getting an empty form if you didn't build your solution, which would result in an error screen when you try to open the form, which you ignored by simply clicking continue. Any unknown controls are then removed from the form.
> 
> Try building the solution (Build menu) and the WizardCtrl control should appear at the top of the Toolbox.


Yeah, i built the solution then run the solution.
I don't receive any errors or warnings either.

Screenshot below:

----------


## NickThissen

Is it a blank form in the designer too? Can you try opening the Document Outline window (from the View menu) and look which controls are on the form, if any?

If there aren't any, try adding the WizardCtrl control that should be on the top of your Toolbox once you built the solution.

----------


## r000t

> Is it a blank form in the designer too? Can you try opening the Document Outline window (from the View menu) and look which controls are on the form, if any?
> 
> If there aren't any, try adding the WizardCtrl control that should be on the top of your Toolbox once you built the solution.


Yeah, and there are no control when i open use Document Outline.

And the WizardCtrl control doesn't appear on top of the Toolbox when the project is built.

Any ideas?

----------


## NickThissen

Do you get any errors when building? Does it say Build succeeded in the lower left corner, or does it say Build failed? 

Try creating a new project and using Add Existing Items to add the files to your new project:
    * WizardCtrl.vb
    * WizardPage.vb
    * WizardCtrlDesigner.vb
    * WizardPageDesigner.vb
    * Misc.vb
You will probably also need to add a reference to System.Design.

Then try to build your solution. If that doesn't work and you get no errors, I have no idea what's going on. If you do get errors, tell me which ones.

----------


## DaneX

Doesn't work! The style doesn't change... any help please?

----------


## NickThissen

Sorry, what are you talking about? The style? Change into what..? 

Do you mean aero glass doesn't work? Do you have Windows Vista, or possibly Windows 7?

----------


## r000t

Hi Nick,

Read your first post and found the answer for my first question...

2nd..

Currently the "Cancel" button doesn't do anything on the wizard, how can i add code behind the button?

Thanks.

----------


## NickThissen

Hi. Can you reproduce that in a new project perhaps? I've encountered something like that before, but simply selecting a different page always solved the bug and I was able to select the page I wanted again. 

For the cancel button, there is a CancelButtonClicked event, just as there are Next/BackButtonClicked events (in which you can (for example) cancel the navigation or something).

----------


## r000t

Oh, got it. Thanks!

----------


## r000t

Nick,

Is there a a way you can link to a certain page in a wizard control?

For example, I have a button in a toolstrip that I want to link to a page i have on a wizard control. Can I link this button to a wizard page?

Also, how do i add a new wizard to my project? I can't simply drag a new wizard control onto a form because i want to change the design of the wizard control (remove the buttons). I've tried simply copy and pasting the 'controls' and 'designers' folders but this returns an error. Can you tell me a simpler way to achieve this?

Thanks.

----------


## NickThissen

What do you mean by 'link' a button to a page? Do you mean you want to show a wizard page when you click that button? If so, you can just set the SelectedIndex or SelectedPage properties in the button click event.


And if you want to change the design of the wizard, there is only one option, simply by modifying the source files. You should have them in your project already, otherwise how are you using the wizard at all? 

Or do you mean using the wizard in a _new_ project instead of the example project I provided? In that case, you would add the required files to your project. The required files are not _all_ files in the folders you mention, because VB will automatically 'imply' those for you. The files you need to add are the files I listed at the bottom of the very first post.

The error you are probably getting either has to do with you adding too many files, or (if not) you forgot to Build your project. After adding the required files, and also after making any changes, you should always Build your project. If you don't do this, the main project does not know about my control, and hence has no idea what the heck that 'WizardCtrl1' object on the form is. 

One more note, if you are going to edit the control, you generally would not have to touch the Designer files, unless you're radically changing it. I'm not objecting to you radically changing it (by all means try!) but just a note that the designer files are quite complicated. Even I don't understand much of it exactly, it was more or less trial and error and looking at other codes.

----------


## r000t

Yeah, I have a button on a form named frmLogin and I want to show form with a specific wizard page selected (on a different form) when the button is clicked.

And, I guess i'll have to go editing the source code then for the other problem.

----------


## NickThissen

What other problem? 

Just out of curiosity, why would you remove the buttons from the wizard? It defeats the whole purpose of the wizard, that users are able to browse through the pages. If you take away the buttons it's just a bunch of panels on top of each other with no way to navigate between them. 
If that is exactly what you need (and I assume you would navigate between panels in code?) then maybe you want to take a look at the Panel Manager on this website, which was actually the basis for my wizard.
There's also a codebank submission right here about the same control.
This Panel Manager is basically my wizard control, without the buttons and title/description bar.

----------


## r000t

I have one of your controls acting as a wizard, but i want another one (with no buttons) basically, so I can have multiple pages on one form.

I'll check out the panel manage now.

----------


## NickThissen

You already have multiple pages on one form, all in the one wizard control. Or is that not what you meant lol.

----------


## r000t

> You already have multiple pages on one form, all in the one wizard control. Or is that not what you meant lol.


lol, what i used to have to do was create multiple panels and hide them until i want to show them. When i needed to edit a page, it used to be a pain in finding the right panel on a form.

I would use the wizard control for this, but i don't want the user to be able to navigate between the pages, instead, i want to show a specific page when a button is clicked.

Hope this is clearer?

----------


## NickThissen

Yes, that is the reason I created this wizard control. It still simply does nothing more than hiding and showing panels, but it makes the design time so much more easier since you can also navigate between the panels during design time. 

If you don't want the users navigating, you should use the Panel Manager I linked to. It is nothing more than a 'background panel' into which you dock more Panels. You can switch panels using the SelectedPanel property which is also available in the Action Lists during design time (click the [>] button on the top right corner). 

The Panel Manager is the basis for my control. All I did was build the wizard interface around it, and allowed you to control the buttons during design time.

----------


## r000t

Hi Nick,

I've been using the Panel Manager for quite a while now but i'm stuck on getting a For Each loop for work.

Here is what i have:



```
            Dim Panel As Panel
            For Each Pannel In pmStudentHome.ManagedPanels
                ' My Code Here
            Next
```

But this isn't right. Any idea what i have to put after the each code?

Thanks.

----------


## NickThissen

Wel, in each case not "Pa*nn*el", but I assume that's a typo. 

I think the panels in the PanelManager are custom panels called ManagedPanel or something. So you might want to try


```
For Each p As ManagedPanel In pmStudentHome.ManagedPanels
...
Next
```

----------


## r000t

Hi,

I'm having a little trouble.

I have added the necessary files to my project and referenced System.Design...



 but i'm still getting a bunch of errors...



Any ideas?

Thanks.

----------


## NickThissen

One thing I see is the 3DLine classes. I'm pretty sure they are all supposed to be called 'ThreeDLine', and the .designer.vb and .resx files should be hidden underneath the main ThreeDLine.vb file (in the solution explorer treeview). Did you rename them? Or are they actually like that in the download? I've no time to try right now. Try renaming them to the same name and then removing and re-adding them to the project.

The other errors do look like you did not reference System.Design... Can you verify that you did, by expanding the References 'folder' in the solution explorer? If that folder is not visible click the Show All Files button at the top first.

----------


## r000t

I didn't rename any files, just imported them from the example project you provided in your first post.

I did however have to download the System.Design library as i didn't have it for some reason. The only thing i can think of is that this is an old library.

Can you confirm that this is the version you have?:

----------


## NickThissen

No, I have at least version 2. I think the version corresponds to your .NET framework version. I created this first in VS2005 I think (or I was targeting framework 2.0, not sure) so it is version 2. It is still version 2.0 when I add the reference in a new (VS2008 / Framework 3.5) project. Apparently it didn't get any updates I suppose?

Since you are using VS10 with .NET Framework 4.0 the version should be at least 2.0 (or 4.0 if something was updated, I don't think so). Since it is only 1.0.5 I can only conclude that you downloaded a .NET Framework 1.0 version. I think it's very strange that you don't have the System.Design dll though :S It must have something to do with VS10... I don't really know, sorry! Try re-installing it (along with the framework) perhaps?

I'm pretty sure that, once you can Build your solution (which is after you added the correct reference), the 3DLine control errors will go away too. If not, you can always remove it as it doesn't add much value; it just draws a 3d-looking line near the white/gray interface in the wizard. If you really want that line you can always use a different 3d line drawer (I made one too a while ago, but you can also use a groupbox with a 2px width for the same effect).

----------


## r000t

Yeah, i don't know why it didn't install with the framework.

I'll see if I can download an updated version from somewhere, and hopefully the error will disappear.

Ty

----------


## Brainsturbator

Hey Nick is there a way I can contact you? I registered here just to ask you a question but I don't want to do it randomly in a unrelated thread :P

----------


## NickThissen

You can send me a PM. But if it's unrelated to this thread then what is it related to? If it is a general programming question then just ask it in the correct forum so that others can help you too.

----------


## weirddemon

Nick,

When playing around with your control, I'm not able to see a change when the visible property of a page is set to False.

Whether I set it in the designer or during run time, it doesn't reflect when changing pages.

Do you know why this might be?

Thanks

----------


## NickThissen

Hm, why are you setting the visible property to false? 

I think I'm using the visible property to hide/show the pages when appropriate (alongside bringing them to the front). So it is going to be changed all the time by the container control, when you change the selected page.

----------


## weirddemon

I have 4 CheckBoxes that allows the user to select which pages they need to use. If, for instance, they only need to work with the content that is on page 2, I need to be able to not show pages 1, 3, and 4.

----------


## NickThissen

That's not usually how a wizard works, but ok  :Stick Out Tongue: 

Hm. I'm not too sure how to approach this. You can handle the button events (I think there's NextButtonClicked, etc), which should have a Cancel property in the event arguments (e). Well, I showed someone how to add that property once, I'm not really sure if I've added it to the actual project yet.
Anyway, that would allow you to cancel navigation when you don't want it.

----------


## weirddemon

Thanks for the info, Nick.

I'll play around with it to see what I can figure out.




> That's not usually how a wizard works, but ok


Yeah... I guess not. I need the functionality of a wizard, with this specific option. And since this part of the GUI is integral to the main functionality of the app, I can't move forward until I get this figured out.

Thanks again  :Big Grin:

----------


## weirddemon

Nick,

When trying to import your control into a new project, instead of testing out the project example, I'm not able to fully import the ThreeDLine.vb file.

When importing WizardCtrl.vb and WizardPage.vb, it imports the appropriate designer and resx files. When importing the ThreeDLine.vb file, it doesn't import the 3DLine.Designer.vb and 3DLine.resx files. I can import them separately, but they aren't tied to the 3DLine.vb file.

Do you know why this might be? Could it be something with what VS you developed it in? I think you must have used VS 2005 to develop it since it has me upgrade the files prior to opening the project.

----------


## NickThissen

Hm, perhaps it has to do with the name... Try renaming all files to the same name (ThreeDLine instead of 3DLine, I don't know if you can use numbers) before adding the file.
Not sure why I didn't get that. I can't remember if I made this in VS2005 but I used it in VS2008 as well, pretty sure about that.

----------


## weirddemon

It seems the naming was the issue.

Thanks

----------


## Pc_Not_Mac

Great project i just have a question how can you add these two navigation buttons?

----------


## NickThissen

I'm sure you can just place two images there with some mouse hover and click events. Although the background between the images is probably a little more difficult.

----------


## Pc_Not_Mac

I see thanks for the reply.

----------


## arcanine

I hate to bump an old thread, but I'm having a redraw/cleanup issue with the wizard control.  I've done the following:

Downloaded latest non-Aero versionRename appropriate ThreeDLine filesCreate new project in VS 2008Add existing items...selected source filesBuild projectAdd wizard control to userformset wizard control DockStyle to FillDebug/Run projectStop debugging

After this, the design-time view of my userform no longer shows the wizard control.  Closing the userform's designer and reopening it fixes the problem.  Is this some sort of dispose/finalize bug?  I don't know enough about .Net and/or user controls to really track what is happening.

The two images display what I'm trying to write.  The first is a view of my project before I debug/run.  The second is after I stop debugging.  When I close and reopen formMain.vb, everything looks like the first image again.

Thanks.

----------


## NickThissen

I'm not sure what is causing the problem, but I do have a workaround (that's actually better practice then what you are doing). Instead of dumping all the files in your Windows Forms Application project, add a new Windows Forms Control Library project to your solution (I am assuming you're using Visual Studio and not one of the Express versions). Then add the files to that control library project (be sure to reference System.Design) and reference the control library project from your main project. When doing this, the control no longer disappears from my form. Again, I have no idea why, but it works for me.

If you do have the Express versions, you can always create a new Class Library project (I don't think Control Library is available in Express?), add the required references (System.Windows.Forms probably and maybe some others), and build it. Then you get a DLL file that you can reference from your main project, and it should work the same.

----------


## arcanine

Okay thanks.  I'll have to try the Express version of your work-around.

----------


## arcanine

Work-around is great!  Also, before I tried your work-around, I discovered that if I added a second wizard page to the control (during design-time), the disappearing control problem went away.

Also, the updated wizard control that includes the cancel button_press events, removed the code that toggles the visibility of the header panel based on the value of a wizard page's IsWelcomePage property.  The code for the cancel event wizard control:


```
    Public Overridable Sub OnSelectedPageChanged(ByVal e As EventArgs)
        Static oldSelection As WizardPage = Nothing
        If Not (oldSelection Is Nothing) Then
            oldSelection.Visible = False
        End If
        If Not (m_SelectedPage Is Nothing) Then
            CType(m_SelectedPage, WizardPage).Visible = True
        End If
        Dim tabChanged As Boolean
        If m_SelectedPage Is Nothing Then
            tabChanged = Not (oldSelection Is Nothing)
        Else
            tabChanged = Not (m_SelectedPage.Equals(oldSelection))
        End If
        If tabChanged And Me.Created Then
            RaiseEvent SelectedIndexChanged(Me, EventArgs.Empty)
        End If
        oldSelection = CType(m_SelectedPage, WizardPage)

        ' Update title/description/icon
        Dim page As WizardPage = Me.SelectedPage
        If page IsNot Nothing Then

            Me.Invalidate()

            If page.Icon IsNot Nothing Then
                Me.picIcon.Image = page.Icon
                Me.picIcon.Visible = True
            Else
                Me.picIcon.Visible = False
            End If

            btnPrev.Enabled = (Me.SelectedIndex > 0)

            If page.IsLastPage Then
                btnNext.Text = FinishButtonText
            ElseIf page.IsWelcomePage Then
                btnNext.Text = StartButtonText
            Else
                btnNext.Text = NextButtonText
            End If

        End If
    End Sub
```

The code how I modified it:


```
    Public Overridable Sub OnSelectedPageChanged(ByVal e As EventArgs)
        Static oldSelection As WizardPage = Nothing
        If Not (oldSelection Is Nothing) Then
            oldSelection.Visible = False
        End If
        If Not (m_SelectedPage Is Nothing) Then
            CType(m_SelectedPage, WizardPage).Visible = True
        End If
        Dim tabChanged As Boolean
        If m_SelectedPage Is Nothing Then
            tabChanged = Not (oldSelection Is Nothing)
        Else
            tabChanged = Not (m_SelectedPage.Equals(oldSelection))
        End If
        If tabChanged And Me.Created Then
            RaiseEvent SelectedIndexChanged(Me, EventArgs.Empty)
        End If
        oldSelection = CType(m_SelectedPage, WizardPage)

        ' Update title/description/icon
        Dim page As WizardPage = Me.SelectedPage
        If page IsNot Nothing Then
            Me.lblPageTitle.Text = page.Title
            Me.lblDescription.Text = page.Description
            If page.Icon IsNot Nothing Then
                Me.picIcon.Image = page.Icon
                Me.picIcon.Visible = True
            Else
                Me.picIcon.Visible = False
            End If

            btnPrev.Enabled = (Me.SelectedIndex > 0)

            If page.IsLastPage Then
                btnNext.Text = FinishButtonText
            Else
                btnNext.Text = NextButtonText
            End If

            If page.IsWelcomePage Then
                btnNext.Text = StartButtonText
                Me.Top3DLine.Visible = False
                Me.pnlHeader.Visible = False
            Else
                Me.Top3DLine.Visible = True
                Me.pnlHeader.Visible = True
            End If

            Me.Invalidate()
        End If
    End Sub
```

Hopefully that made sense.  The changes come after the comment "Update title/description/icon".

----------


## r000t

Sorry to bump...

Nick, how would I have the form close after the finish button has been clicked?

Currently... This code:



```
    Private Sub wizard_AddSupplier_NextButton_Clicked(ByVal WasLastPage As Boolean) Handles wizard_AddSupplier.NextButton_Clicked
        If (WasLastPage) Then
            If (Supplier.saveSupplier()) Then
                MsgBox("The Supplier with Reference: " + Supplier.Reference().ToString() + ", has been added to the System", MsgBoxStyle.Information, "Supplier Added")
                Me.Close()
            Else
                MsgBox("An error occured when trying to Add the Supplier", MsgBoxStyle.Exclamation, "Unable to Add Supplier")
            End If
        End If
    End Sub
```

Produces, this error:




> Index 0 is out of range.
> Parameter name: index


Thanks.

----------


## NickThissen

Where does that error occur? If you're using the source code you should be able to tell my exactly where it goes wrong. If you are using a compiled version, does it error before it even raises the NextButton_Clicked event or somewhere in your own code?

----------


## r000t

> Where does that error occur? If you're using the source code you should be able to tell my exactly where it goes wrong. If you are using a compiled version, does it error before it even raises the NextButton_Clicked event or somewhere in your own code?


It happens on the 'Set' of the SelectedIndex() Property in WizardCtrl.vb on the line:



```
Me.SelectedPage = DirectCast(Me.Pages(Value), WizardPage)
```

----------


## NoobOne

Hey Nick,

first i want to thank you for this easy to use control  :Smilie: 

and second: did you find a solution for r000t's error? i've got the same, when i try to clode the wizard after clicking the finish-button.

----------


## NickThissen

> Hey Nick,
> 
> first i want to thank you for this easy to use control 
> 
> and second: did you find a solution for r000t's error? i've got the same, when i try to clode the wizard after clicking the finish-button.


Hmm, it seems like it is trying to set the SelectedIndex property to 0, but I don't know why, I'll have to look in the source code, and I won't have time for that soon.

Perhaps one of you can take a look where this happens? Does it happen after the Me.Close call is made, or even before that? If it happens before that line (you can check by putting a breakpoint on the Me.Close call) then it must be somewhere in the Next button clicking event (in the control source). If not, it must be something related to the control being disposed, in which case it might also be an error in the design-time code...

----------


## NoobOne

Thanks for the fast reply. I've checked, where this error exactly occurs:

1. Setting a breakpoint on Me.Close()
2. It jumps into this sub:



```
Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNext.Click
        Dim i As Integer = Me.Pages.Count - 1

        RaiseEvent NextButton_Clicked(CType(Me.Pages(Me.SelectedIndex), WizardPage).IsLastPage)

        If Me.SelectedIndex < i Then
            Me.SelectedIndex += 1
        End If
End Sub
```

3. SelectedIndex is -1 when jumping into above sub
4. the sub sets it to +1 = 0
5. and the error occurs in the Property:


```
Public Property SelectedIndex() As Int32
        Get
            Return Me.Pages.IndexOf(CType(Me.SelectedPage, WizardPage))
        End Get
        Set(ByVal Value As Int32)
            If Value = -1 Then
                Me.SelectedPage = Nothing
            Else
                Me.SelectedPage = DirectCast(Me.Pages(Value), WizardPage)
            End If
        End Set
End Property
```

on this line



```
Me.SelectedPage = DirectCast(Me.Pages(Value), WizardPage)
```

It seems the inital error is in the btnNext_Click-Sub, because there the SelectedIndex is set to a wrong value.

----------


## NickThissen

Ok, thanks. It seems the pages are being disposed from the form once you run the Close call. This happens in the RaiseEvent call from your first code snippet. After that, it sets the SelectedIndex to the next page, but only if there is a next page.

The error is that this "is there a next page?" check is done before the RaiseEvent and thus before all pages are removed. Before the RaiseEvent, i = the number of pages - 1. If nothing happens with the page count in the NextButton_Click event, i doesn't change. But in this case, the page count changes and i is outdated. I think simply moving the assignment of i to behind the RaiseEvent call would fix it:


```
Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNext.Click
        RaiseEvent NextButton_Clicked(CType(Me.Pages(Me.SelectedIndex), WizardPage).IsLastPage)

        Dim i As Integer = Me.Pages.Count - 1
        If Me.SelectedIndex < i Then
            Me.SelectedIndex += 1
        End If
End Sub
```

----------


## NoobOne

That's it.

Now it closes without any errors.

Btw. how you want to be mentioned in a released program? a line in the About-Dialog?  :Big Grin:

----------


## NickThissen

Whatever you want is fine by me  :Smilie:

----------

