views:

63

answers:

3

Hey guys / gals,

I am almost too embarrassed to ask this question, but here we go...

I am not an expert with user controls, and need some design advise regarding trying to achieve a specific desired functionality.

The goal is to have a usercontrol that would render as a complex structure of html elements and css to form an elegant container box. The problem lies in how to populate the contents of the box as each instance of the usercontrol would have its own individual HTML content. The content container div of the usercontrol would be nested deep within the structure of the rendered html. It is undesirable to programmatically set the contents of the usercontrol, or use properties.

In psuedo-code, the desired syntax would be something like:

<usercontrol Title="Some Title"><p>some random html content</p></usercontrol>

A sample of the rendered usercontrol would be:

<div class="CommonBox">
    <div class="Title">Some Title</div>
    <div class="Content"><p>some random html content</p></div>
</div>

I hope my explanation is adequate. Does this make sense to anyone or is the desired functionality unachievable?

Cheers!

EDIT

I attempted the templated user control suggestion in the hopes of coming to a decent solution. I "waybacked" this site and now have a working templated user control. My next question is, how can I programmatically access the controls nested within the template... say there is a textbox control in the "Description" template from the example link and I want to set its value programmatically? Is this possible?

A: 

Hi,

Yes this is very possible. First you can create a custom control as I describe in this post. Properties in the control become attributes like "Title" you have in your example. Then you can extend your control with the technique shown in this post to add child nodes for the other html inputs you will require.

Enjoy!

Doug
I think the second part requires clarification, he's looking to have any content inside his user control, not just specific objects.
Matti Virkkunen
+2  A: 

What you're looking for is definitely possible. One solution is to create a templated user control. In the end you can define the contents similar to how your example looks. Something like:

<uc:MyControl Title="Some TItle" runat="server">
    <ContentsTemplate>
        <p>some random html content</p>
    </ContentsTemplate>
</uc:MyControl>

Here's a simple how-to. I've done this in the past with success. There are lots of resources found through Google as well on the topic.

KP
Templates are a good way to do this. I wonder if there's a reliable and easy way to do this without though, would save one level of elements when using the control. It's easy to do with custom controls, but I haven't really tried with `.ascx` files.
Matti Virkkunen
@Matti: I would think you could create a base class such as `TemplatedUserControl` which takes care of the basic/common functionality. Inheritance would then be `MyControl` > `TemplatedUserControl` > `UserControl`. I've used this approach for other common user control needs and it works great..
KP
@KP: You'll still need `<ContentsTemplate>` whenever you use your control, though. IMO it would be the nicest if the custom decoration acted like, say, `<asp:Panel>` and you could just put it around your stuff (disclaimer: I do not endorse the use of asp:Panel)
Matti Virkkunen
@Matti: Yeah I agree with you there...
KP
A: 

It looks like you need two properties for your custom server control.

Title property to render first inner div's content,

Content for the second one. If you want to set contents inside your server control, you should use [PersistenceMode(PersistenceMode.InnerDefaultProperty)] attribute for your property, like this :

[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public string Contents
{
    get
    {
        string contents = (string)ViewState["Contents"];
        return (contents == null) ? String.Empty : contents;
    }
    set
    {
        ViewState["Contents"] = value;
    }
}

PersistenceModeAttribute is explained in MSDN like that :

PersistenceModeAttribute Passing the InnerDefaultProperty parameter specifies that a visual designer should persist the property to which the attribute is applied as an inner default property. This means that a visual designer persists the property within the control's tags. The attribute can be applied to only one property, because only one property can be persisted within the control's tags. The property value is not wrapped in a special tag.

For more information take a look at the last example here.

Canavar