not persisting control after viewing design time?

A

Allan Ebdrup

I have a custom server web control that inserts another custom web server
control in a templated child control (a wisard that inserts a header in its
wizardstep)
Now after switching to design view and back the header is inserted in the
aspx page's xml. I don't want this because then yet another header is
inserted when I switch to design view again.
I've tried looking through the attributes you can set on a component but I
can't find anything that stops serialization of an entire component, only a
property or event.

How can I stop the design view from actually inserting the header into the
xml of the wizard step template?

Kind Regards,
Allan Ebdrup
 
W

Walter Wang [MSFT]

Hi Allan,

I'm not sure if I fully understand your question. What kind of header in
the WizardStep?

If this is the same control you mentioned in your another post, I think I
can also help you after you send me a reproducible project. Thanks.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Allan Ebdrup

Walter Wang said:
Hi Allan,

I'm not sure if I fully understand your question. What kind of header in
the WizardStep?

If this is the same control you mentioned in your another post, I think I
can also help you after you send me a reproducible project. Thanks.

The header is my own web server user control
I found a solution, instead of adding the header to all the wizardsteps I
add the header in the HeaderContainer of the wizard:
------
protected override void OnInit(EventArgs e)
{
if (ShowCustomHeader)
{
this.HeaderText = " "; //we need this to render header.
Control wizardHeader = this.FindControl("HeaderContainer") as Control;
if (wizardHeader != null)
{
CustomWizardStepHeader header = new CustomWizardStepHeader();
header.CustomWizard = this;
header.ID = "CustomWizardStepHeader";
wizardHeader.Controls.AddAt(0, header);
}
}
base.OnInit(e);
}
------

It doesn't show up in design view, but I guess I can live with that...

Kind Regards,
Allan Ebdrup
Free surveys with AJAX (beta): http://obsurvey.com
 
W

Walter Wang [MSFT]

Hi Allan,

Wizard inherits from CompositeControl. We normally create child controls of
a composite control in the method CreateChildControls.


I suggest you to override CreateChildControls, call
base.CreateChildControls first, then add your custom header. This will make
it also appear in the designer.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Allan Ebdrup

Walter Wang said:
Hi Allan,

Wizard inherits from CompositeControl. We normally create child controls
of
a composite control in the method CreateChildControls.


I suggest you to override CreateChildControls, call
base.CreateChildControls first, then add your custom header. This will
make
it also appear in the designer.

Thank you for your feedback. I've tried your suggestion with the following
CreateChildControls:
--------------
protected override void CreateChildControls()
{
base.CreateChildControls();
if (ShowCustomHeader)
{
Control wizardHeader = this.FindControl("HeaderContainer") as Control;
if (wizardHeader != null)
{
CustomWizardStepHeader header = new CustomWizardStepHeader();
header.CustomWizard = this;
header.ID = "CustomWizardStepHeader";
wizardHeader.Controls.AddAt(0, header);
}
}
}
----------------------

The header shows up fine at run time, but it doesn't show up at design
time...

Kind Regards,
Allan Ebdrup
 
W

Walter Wang [MSFT]

Hi Allan,

Is "ShowCustomerHeader" a property persisted in ViewState?

Could you please put up a complete project and send it to me, I think this
might be related to other parts of your code. Thanks for the trouble.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
W

Walter Wang [MSFT]

Hi Allan,

Thanks for the code you mailed to me.

I just realized that the "HeaderContainer" you're using is actually used to
hold controls in the HeaderTemplate. In this case, dynamic controls added
to it will not work as usual. You will need to create a custom template and
use it as the HeaderTemplate:

public class Class1 : Wizard
{
protected override void CreateChildControls()
{
this.HeaderTemplate = new MyTemplate();
base.CreateChildControls();
}
}

public class MyTemplate : ITemplate
{
public void InstantiateIn(System.Web.UI.Control container)
{
Button button = new Button();
button.Text = "Hello";
container.Controls.Add(button);
}
}

This will also works at design-time.

#Creating Web Server Control Templates Dynamically
http://msdn2.microsoft.com/en-us/library/y0h809ak(vs.71).aspx


#Creating Templates Programmatically in the DataGrid Control
http://msdn2.microsoft.com/en-us/library/aa712868(vs.71).aspx


However, please note at this time, user will not be able to use
<HeaderTemplate> node in your custom wizard since you completely replaced
it; but I think your objective here is to use a built-in header for your
custom wizard control so I think this should not be an issue.

Hope this helps.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Allan Ebdrup

Walter Wang said:
Hi Allan,

Thanks for the code you mailed to me.

I just realized that the "HeaderContainer" you're using is actually used
to
hold controls in the HeaderTemplate. In this case, dynamic controls added
to it will not work as usual. You will need to create a custom template
and
use it as the HeaderTemplate:

I created a header template:

public class CustomWizardStepHeaderTemplate : ITemplate
{
private readonly CustomWizard _customWizard;
public CustomWizardStepHeaderTemplate(CustomWizard customWizard)
{
_customWizard = customWizard;
}
public void InstantiateIn(Control container)
{
CustomWizardStepHeader header = new CustomWizardStepHeader();
header.CustomWizard = _customWizard;
header.ID = "CustomWizardStepHeader";
container.Controls.Add(header);
}
}

And I use it in CreateChildControls:

protected override void CreateChildControls()
{
if (ShowCustomHeader)
{
this.HeaderTemplate = new CustomWizardStepHeaderTemplate(this);
}
base.CreateChildControls();
}

The header still does not show up in design view. It does show up correctly
at runtime...

I'll take a look at the links you send.

Kind Regards,
Allan Ebdrup
 
A

Allan Ebdrup

OK
I changed the controls a bit changing where things are done according to
what I've learned from looking at the decompiled versions of the .net
webcontrols. Now the header shows up in design view.
However I changed another control also and now it doesn't show up in design
view, here is the code for the control that doesn't show up in design view:
--------
public class CustomWizardNavigation : Control, INamingContainer,
ICustomWizardChild
{
private readonly Button _cancelButton = new Button();
private readonly Button _nextButton = new Button();
private readonly Button _previousButton = new Button();
private CustomWizard _customWizard;
private Button PreviousButton
{
get { return _previousButton; }
}
private Button NextButton
{
get { return _nextButton; }
}
private Button CancelButton
{
get { return _cancelButton; }
}
public CustomWizard CustomWizard
{
get { return _customWizard; }
set
{
_customWizard = value;
}
}
protected override void CreateChildControls()
{
Table t = new Table();
t.CellPadding = 5;
t.CellSpacing = 5;
t.BorderWidth = 0;
Controls.Add(t);
TableRow tr1 = new TableRow();
t.Controls.Add(tr1);
TableCell tc1 = new TableCell();
tr1.Controls.Add(tc1);
PreviousButton.ID = "StepPreviousButton";
tc1.Controls.Add(PreviousButton);
PreviousButton.Click += previousButton_Click;
TableCell tc2 = new TableCell();
tr1.Controls.Add(tc2);
NextButton.ID = "StepNextButton";
tc2.Controls.Add(NextButton);
NextButton.Click += nextButton_Click;
TableCell tc3 = new TableCell();
tr1.Controls.Add(tc3);
CancelButton.ID = "CancelButton";
tc3.Controls.Add(CancelButton);
CancelButton.Click += cancelButton_Click;
//these texts will be overwritten when the control is rendered, we only set
them here for design view
PreviousButton.Text = "< Tilbage";
PreviousButton.CssClass = "pcb0";
NextButton.Text = "Næste >";
NextButton.CssClass = "pcb0";
CancelButton.Text = "Annuller";
CancelButton.CssClass = "pcb0";
base.CreateChildControls();
}
private void cancelButton_Click(object sender, EventArgs e)
{
CustomWizard.OnCancelButtonClick(e);
}
private void nextButton_Click(object sender, EventArgs e)
{
if (CustomWizard.ActiveStepIndex < CustomWizard.WizardSteps.Count - 1)
CustomWizard.ActiveStepIndex++;
}
private void previousButton_Click(object sender, EventArgs e)
{
if (CustomWizard.ActiveStepIndex > 0) CustomWizard.ActiveStepIndex--;
}
protected override void Render(HtmlTextWriter writer)
{
ApplyControlProperties();
base.Render(writer);
}
private void ApplyControlProperties()
{
if(CustomWizard==null) return; //for design view
PreviousButton.Text = CustomWizard.StepPreviousButtonText;
PreviousButton.CssClass = CustomWizard.StepPreviousButtonStyle.CssClass;
if (CustomWizard.ActiveStep.StepType == WizardStepType.Finish)
{
NextButton.Text = CustomWizard.FinishCompleteButtonText;
NextButton.CssClass = CustomWizard.FinishCompleteButtonStyle.CssClass;
}
else
{
NextButton.Text = CustomWizard.StepNextButtonText;
NextButton.CssClass = CustomWizard.StepNextButtonStyle.CssClass;
}
CancelButton.Text = CustomWizard.CancelButtonText;
CancelButton.CssClass = CustomWizard.CancelButtonStyle.CssClass;
}
}
--------

I can't figure out why this control does not show correctly in design view.
It runs correctly at runtime.
I'm using it in an .ascx file that I insert in a wizard step.

If I change the control so that I add the child controls in OnInit instead,
it shows up fine in design view.

I thought I was supposed to create child controls in the CreateChildControls
method?!?

Kind Regards,
Allan Ebdrup
 
A

Allan Ebdrup

I found that I was missing EnsureChildControls in the Render method...

Now everything works.

Thanks for the help.

Kind Regards,
Allan Ebdrup
 
W

Walter Wang [MSFT]

Hi Allan,

For a composite control, you should inherit from WebControl and
INamingContainer; or better (in ASP.NET 2.0), inherit from CompositeControl.

Also there're some best practice when creating composite control, please
follow the example code here:

#A Crash Course on ASP.NET Control Development: Building Composite Controls
http://msdn2.microsoft.com/en-us/library/aa479016.aspx


Hope this helps.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
W

Walter Wang [MSFT]

Hi Allan,

My previous answer is not completely correct, inheriting from WebControl
and INamingContainer will still not make the child controls show at
design-time. You will need to implement ICompositeControlDesignerAccessor
(http://msdn2.microsoft.com/en-us/library/system.web.ui.webcontrols.icomposi
tecontroldesigneraccessor.aspx) to allow a composite-control designer to
recreate the child controls at design time.

CompositeControl in 2.0 inherits from WebControl and implements
INamingContainer, ICompositeControlDesignerAccessor:

CompositeControl : WebControl, INamingContainer,
ICompositeControlDesignerAccessor


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top