views:

87

answers:

2

I am writing what i will call a survey system. The surveys will consist of a series of questions, split into sections. The survey definitions will be stored in a database. The questions can be of various types, that have different input methods and validation (e.g.textbox, numeric textbox, selectlist etc.) I am creating a set of user controls that map to different question types. I would like to completely abstract the survey rendering logic from the, survey definition logic. The way i thought i would do this is to use a dumb rendering control that simply takes a collection of controls and renders them out in a for each loop a super simplified version of what I am doing.

private void RenderControls()
{
    foreach (UserControl CurrentControl in this.ControlsToRender)
    {
        MyPlaceholder.Controls.Add(CurrentControl)
    }

}

This works in the sense that the correct controls get added to the place holder,however nothing renders. Presumably this is because it does not have the markup in the asxc file.

If i do something like this

private void RenderControls()
{
    foreach (UserControl CurrentControl in this.ControlsToRender)
    {
        MyPlaceholder.Controls.Add(this.LoadControl("path to ascx file")
    }
}

It will create the correct number of controls, but i don't want to instantiate the controls here because i would need to to set various properties based on cconditional logic i want to abstract away from this pure rendering layer.

what i want to do is instantiate the controls else where, set the relevant properties and then simply pass a collection of these into the rendering control to render out.

Is there a way to do this with user controls? Would i have to create custom controls instead?

+1  A: 

.ascx usercontrols are difficult to make into distributable, portable components. There are ways of doing it, but they have a lot of restrictions and requires several steps. In the end it's not worth it.

Your best bet would be to make custom controls that encapsulate their own rendering.

womp
That is what I figured, I was hoping there was a way to do this without having to write my own render methods.
Ben Robinson
The easiest thing is just to make your custom controls extend Panel, and then in their constructor, just add all the layout and subcontrols to their own Controls collection. You never have to write any rendering logic this way - you can just arrange everything in the Controls collection.
womp
@womp - ah of course i think that is the way to go here.
Ben Robinson
A: 

You could do either, but it sounds to me like you might want to use custom controls.

You could use user controls by exposing properties on the user control.

MyPlaceholder.Controls.Add(CurrentControl)

by the time you get to the above line, the control has already been instantiated. just set those properties on instantiation and you should be set.

alternatively you could set the properties anytime before render

statichippo
The problem is not setting the properties or instantiating the control, that is done elsewhere and works fine. The problem is that they don't render anything, because there is no markup for them, this is stored in the ascx file.
Ben Robinson