New Wizard Control - Bugs/Issues

Using the new wizard control in ASP.NET 2/Visual Studio 2005 and I ran into a few oddities. Anyone else run into this or use the wizard control much?

  1. I cannot access controls inside of the wizard templates like the StartNavigationTemplate for example. I’ve tried several methods including the FindControl() method and none of them work. I get an object reference error.

  2. I have a similar issue with any control inside of the wizard steps. It doesn’t throw an error, but VS can’t find them in intellisense and draws a line under them as a potential problem.

I think you are expecting it to be more complicated than it really is: The controls of the steps are actually controls of the page.

In this wizard:

        <asp:Wizard ID="Wizard1" runat="server">
            <WizardSteps>
                <asp:WizardStep ID="WizardStep1" runat="server" Title="Step 1">
                    <asp:TextBox ID="txtFirst" runat="server"></asp:TextBox>
                </asp:WizardStep>
                <asp:WizardStep ID="WizardStep2" runat="server" Title="Step 2">
                </asp:WizardStep>
            </WizardSteps>
        </asp:Wizard>

txtFirst will be accessible simply as a member field of the page.

(which is actually quite neat, as all of the controls of all the steps are readily accessible at the final step. It also lets you rearrance controls between the steps without having to change any code)

Thanks to a [TemplateInstance(TemplateInstance.Single)] Attribute on the WizardStep Template. :slight_smile:

Benjymouse
Yes, the controls in the wizard steps I can access and that does not cause a problem. I was saying VS does not see them - if I type in txtFirst.Text or something it draws a line under it and says there no such thing. It’s the controls in the navigation templats that cause the error.

pufa
Thanks but I don’t quite follow. Here is the control I am trying to get in the template - it’s an image button using the default ID.


   <StartNavigationTemplate>
     <table border="0" width="845" cellspacing="0" cellpadding="0">
   	<tr>
   	  <td width="375">&nbsp;</td><td width="470">
 		<asp:ImageButton ID="StartNextButton" runat="server" CommandName="MoveNext" ImageUrl="Images/next.gif" AlternateText="Next" BorderWidth="0" />
   	  </td>
   	</tr>
     </table>
   </StartNavigationTemplate>
   

I’ve read your post to quickly!! I was cometing mouse post.

I turns out that the StartNavigationTemplate of the Wizard control is not marked with [TemplateInstance(TemplateInstance.Single)] attribute.
Wizard steps templates are.

So I guess you have to use FindControl on the wizard controls collection to get a refence to the controls in the start template.


[size=1][color=#008000]// 
[/color][/size][color=#008000]// Summary: 
[/color][color=#008000]// Gets or sets the template that is used to display the navigation area on 
[/color][color=#008000]// the System.Web.UI.WebControls.WizardStepType.Start step of the System.Web.UI.WebControls.Wizard 
[/color][color=#008000]// control. 
[/color][color=#008000]// 
[/color][color=#008000]// Returns: 
[/color][color=#008000]// An System.Web.UI.ITemplate that contains the template for displaying the 
[/color][color=#008000]// navigation area on the System.Web.UI.WebControls.WizardStepType.Start for 
[/color][color=#008000]// the System.Web.UI.WebControls.Wizard. The default is null. 
[/color][[color=#008080]Browsable[/color]([color=#0000ff]false[/color])] 
[[color=#008080]DefaultValue[/color]([color=#800000]""[/color])] 
[[color=#008080]PersistenceMode[/color](1)] 
[[color=#008080]TemplateContainer[/color]([color=#0000ff]typeof[/color]([color=#008080]Wizard[/color]))] 
[color=#0000ff]public[/color] [color=#0000ff]virtual[/color] [color=#008080]ITemplate[/color] StartNavigationTemplate 
{ 
[color=#0000ff]get[/color]; 
[color=#0000ff]set[/color]; 
} 

edited:
I was wrong again!! WrizardSteps don’t have ITemplate properties, Controls inside the WizardStep are added to the Page by means of a ControlBuilder, the WizardStepControlBuilder.

Whoa. I didn’t even know about the ControlBuilder. Well I sorta did, but my conception was completely off. Another seriously cool customization option built into asp.net.

Makes my head spin. Must find a way to use this cool tech.

^^^^

Crackhead <g>

OK - So is there anyway to get at this control then? They make the templates accessible so I would think you would have someway to get at the ‘StartNextButton’ control.

I think you are probably going to want to use the MultiView control instead.

PS: I have not yet had a chance to read it, but I suspect that this article might be of some help.

From MSDN StartNavigationTemplate property description.

“To access a control that is defined in a template programmatically, use the Controls collection of the Wizard object. You can also use the FindControl method of the Wizard object to find the control, if the control has an ID property specified.”

I’ve tried to access the control inside the StartNavigationTemplate following the above instructions with no luck!


[color=#0000ff]if[/color][color=#000000] ( Wizard1.FindControl([/color][color=#800000]"btnNext"[/color][color=#000000]) != [/color][color=#0000ff]null[/color][color=#000000] )[/color]
{
[color=#008080]Button[/color] btn = Wizard1.FindControl([color=#800000]"btnNext"[/color]) [color=#0000ff]as[/color] [color=#008080]Button[/color];
btn.Text = [color=#800000]"hello!"[/color];
[size=1][size=2]}[/size]
[/size]

The I turned on Tracing on the page and found this…


Wizard1$[b]StartNavigationTemplateContainerID [/b]		[b]System.Web.UI.WebControls.Wizard+StartNavigationTemplateContainer[/b]
Wizard1$StartNavigationTemplateContainerID$ctl00 System.Web.UI.LiteralControl
Wizard1$StartNavigationTemplateContainerID$lblTest System.Web.UI.WebControls.Label
Wizard1$StartNavigationTemplateContainerID$ctl01 System.Web.UI.LiteralControl
Wizard1$StartNavigationTemplateContainerID$btnNext System.Web.UI.WebControls.Button
Wizard1$StartNavigationTemplateContainerID$ctl02 System.Web.UI.LiteralControl

Next I made a break point on page load and started looking for that
StartNavigationTemplateContainer. Look at the Image :slight_smile:

So, unless I’m accessing the control at the wrong time. I think not!!
Control inside the StartNavigationTemplate aren’t added to the “root” of the wizard controls collection but are added to collection of a System.Web.UI.WebControls.Wizard.StartNavigationTemplateContainer that I can’t find in MSDN documentation. :slight_smile:

to access the control inside the StartNavigationTemplate you would have to do something like the following.


Control myControl = Wizard1.Controls[0].Controls[0].Controls[1].Controls[0].Controls[2].Controls[0].Controls[0].FindControl("YourControlId");

cheers,
rui

On the first part I am not familiar with accessing controls through a collection, but I tried adding the code below and nothing printed out.


 If Not Page.IsPostBack Then
 			For Each c As Control In Me.Wizard1.Controls
 			    Me.lblMessage.Text += c.ID & "<br>"
 			Next
 		End If
 

On the second part, I have tried using the FindControl method, FindControl(“StartNextButton”) - Page.FindControl(“StartNextButton”) - Wizard1.FindControl(“StartNextButton”), and none of them work. They all return an error that the object cannot be found.

Try this and see if it works…

Button StartNextButton= (Button) Wizard1.Controls[0].Controls[0].Controls[1].Controls[0].Controls[2].Controls[0].Controls[0].FindControl(“StartNextButton”);

Insane!! but that’s here you will find them!!

No good either - index out of range. Guessing my control isn’t exactly at the same place your’s is, but I have no idea how you got there.

oh, well!

Than I guess you should do what the Asp.net developers forgot to do!!


[color=#0000ff]using[/color][color=#000000] System;[/color]
[color=#0000ff]using[/color][color=#000000] System.Web.UI;[/color]
[color=#000000][/color] 
[color=#0000ff]namespace[/color][color=#000000] Rss.Web.UI.WebControls[/color]
{
[color=#0000ff]public[/color] [color=#0000ff]class[/color] [color=#008080]SmartWizard[/color] : System.Web.UI.WebControls.[color=#008080]Wizard[/color]
{
[[color=#008080]TemplateInstance[/color]([color=#008080]TemplateInstance[/color].Single)]
[color=#0000ff]public[/color] [color=#0000ff]new[/color] [color=#008080]ITemplate[/color] StartNavigationTemplate
{
[color=#0000ff]get[/color] { [color=#0000ff]return[/color] [color=#0000ff]base[/color].StartNavigationTemplate; }
[color=#0000ff]set[/color] { [color=#0000ff]base[/color].StartNavigationTemplate = [color=#0000ff]value[/color]; }
}
}
[size=1][size=2]}[/size]
[/size]

controls in the StartNavigationTemplate are added to the Page, not to the wizard.

i had a similar problem in that web user controls that contained controls weren’t being validated.

I just got rid of the webusercontrol and added the asp.net controls directly to each wizardstep. I’m happy now.

I had Exactly this problem and there is a simple solution:.

If you are using a WizardTemplate you must reference the template Container namespace to use findControls

e.g.
DropDownList ddlTemplates = (DropDownList)NewJob.ContentTemplateContainer.FindControl(“ddlTemplate”);

With Ordinarily Wizard steps you can reference the contained controls directly.

I got the answer here: http://www.asp.net/QuickStart/util/srcview.aspx?path=~/aspnet/samples/ctrlref/standard/Wizard/WizardTemplatedStep.src

Thanks for your help, however, these aren’t templated wizard steps like that. These are the StartNavigationTemplate, StepNavigationTemplate, and FinishNavigationTemplate templates. They do not have the propertyof the templated step in your example/article.

I think pufa might be onto something, but I am not sure how to implement the code. I don’t believe that will create an actual user control/tag that I can put in the body of the page.

My solution is easy. You just create a new WebControl (SmartWizard in my example), in a separate class library project, that inherits from the wizard control and use this new control instead to the normal wizard control.

In the SmartWizard you just “shadow” (VB term for the new keyword in C#) the StartNavigationTemplate, StepNavigationTemplate and FinishNavigationTemplate properties and add a [[color=#008080]TemplateInstance/color] attribute to each of the properties.
This will make the Page the TemplateContainer of the controls inside the wizard templates. So the control inside the template will be first childs of the Page.

This could cause some unespected behavior on the wizard, you will have to test/use it to find out.

using the custom wizard is easy also.


<%-- Resisters the smart wizard assembly on the page --%>[size=1]
<%[/size][color=#0000ff]@[/color][color=#800000]Register[/color][color=#ff0000]Assembly[/color][color=#0000ff]="Rss.Web"[/color][color=#ff0000]Namespace[/color][color=#0000ff]=" Rss.Web.UI.WebControls" [/color][color=#ff0000]TagPrefix[/color][color=#0000ff]="rss"[/color] %>
 
[size=1][color=#0000ff]<[/color][/size][b][color=#800000]rss[/color][color=#0000ff]:[/color][color=#800000]SmartWizard[/color][/b][color=#ff0000]ID[/color][color=#0000ff]="SmartWizard"[/color][color=#ff0000]runat[/color][color=#0000ff]="server"[/color][color=#ff0000]ActiveStepIndex[/color][color=#0000ff]="0">[/color]
[color=#0000ff]<[/color][color=#800000]StartNavigationTemplate[/color][color=#0000ff]>[/color]
[color=#0000ff]<[/color][color=#800000]asp[/color][color=#0000ff]:[/color][color=#800000]Button[/color] [color=#ff0000]ID[/color][color=#0000ff]="btnNext"[/color] [color=#ff0000]runat[/color][color=#0000ff]="server"[/color] [color=#ff0000]CommandName[/color][color=#0000ff]="MoveNext"[/color] [color=#ff0000]Text[/color][color=#0000ff]="Move Next"[/color] [color=#0000ff]/>[/color]
[color=#0000ff]</[/color][color=#800000]StartNavigationTemplate[/color][color=#0000ff]>[/color]
[color=#0000ff]<[/color][color=#800000]WizardSteps[/color][color=#0000ff]>[/color]
[color=#0000ff]<[/color][color=#800000]asp[/color][color=#0000ff]:[/color][color=#800000]WizardStep[/color] [color=#ff0000]runat[/color][color=#0000ff]="server"[/color] [color=#ff0000]StepType[/color][color=#0000ff]="Start"[/color] [color=#ff0000]Title[/color][color=#0000ff]="Step 1">[/color]
Step 1
[color=#0000ff]</[/color][color=#800000]asp[/color][color=#0000ff]:[/color][color=#800000]WizardStep[/color][color=#0000ff]>[/color]
[color=#0000ff]<[/color][color=#800000]asp[/color][color=#0000ff]:[/color][color=#800000]WizardStep[/color] [color=#ff0000]runat[/color][color=#0000ff]="server"[/color] [color=#ff0000]Title[/color][color=#0000ff]="Step 1">[/color]
Step 2
[color=#0000ff]</[/color][color=#800000]asp[/color][color=#0000ff]:[/color][color=#800000]WizardStep[/color][color=#0000ff]>[/color]
[color=#0000ff]<[/color][color=#800000]asp[/color][color=#0000ff]:[/color][color=#800000]WizardStep[/color] [color=#ff0000]runat[/color][color=#0000ff]="server"[/color] [color=#ff0000]Title[/color][color=#0000ff]="Step 1">[/color]
Step 3
[color=#0000ff]</[/color][color=#800000]asp[/color][color=#0000ff]:[/color][color=#800000]WizardStep[/color][color=#0000ff]>[/color] 
[color=#0000ff]</[/color][color=#800000]WizardSteps[/color][color=#0000ff]>[/color]
[color=#0000ff]</[/color][b][color=#800000]rss[/color][color=#0000ff]:[/color][color=#800000]SmartWizard[/color][/b][size=1][color=#0000ff][size=2]>[/size]
[/color][/size][size=1]
[/size]

then in you can access the control inside the template directly


[color=#0000ff]protected[/color][color=#0000ff]void[/color][color=#000000] Page_Load([/color][color=#0000ff]object[/color][color=#000000] sender, [/color][color=#008080]EventArgs[/color][color=#000000] e)[/color]
{
[b][color=#008080]btnNext.Text = [color=#800000]"Hello World!"[/color];[/color][/b]
[size=1][size=2]}[/size]
[/size]

Funny, I just came back to grab the code because I now know what to do with it :slight_smile:

I am still new to VS and all of the wonderful things it can do (verses writing code in Dreamweaver).