views:

264

answers:

4

Basically I want to be able to have a custom control:

public class MyControl : WebControl
{
     private string html;

     public string Html
     { 
         get { return html; }
         set { html = value; }
     }
}

And then in an ASPX page use it like this:

<tag:MyControl runat="server">
    <div>
        <span>Some Text</span>
        <button>Do Something</button>
    </div>
</tag:MyControl>

And then the HTML that is inside the tag:MyControl start and close tags is put into the HTML property of the control.

Is this possible? I'm sure it is, I just don't have a whole lot of experience with custom ASP.Net controls.

+2  A: 

You could create a Literal control (programmatically) and add it to the custom control's Controls collection. Then set the Literal's Text property from the Html Property:

Create the Literal (e.g. in OnInit):

_literal = new Literal();
Controls.Add(_literal);

Html property:

public string Html
{ 
     get { return _literal.Text; }
     set { _literal.Text = value; }
}
M4N
I'm not creating a UserControl, I'm creating a custom WebControl.
Max Schmeling
Then create the Literal control programmatically, and add it to the custom control.
M4N
Updated the answer.
M4N
Either way, this wouldn't answer the question. I want to know how to get the HTML into the HTML property from the aspx code... not get it onto the screen programatically.
Max Schmeling
+1  A: 

I guess you'll want to look at templated controls. See here and here for examples.

(I'll delete my other answer, since I seemed to miss the point).

M4N
Wow that is a lot more work than I thought it would be. I was hoping ASP.Net would support just putting the content of the control into a string... *sigh*
Max Schmeling
+1  A: 

You could do something along the lines of this

public class TestControl : WebControl
{
    public ITemplate Html { get; set; }
    protected override void Render(HtmlTextWriter writer)
    {
        var stringWriter = new StringWriter();
        var htmlWriter = new HtmlTextWriter(stringWriter);
        var control = new Control();
        Html.InstantiateIn(control);
        control.RenderControl(htmlWriter);

        // now you can use the text as you want
        var htmlString = stringWriter.GetStringBuilder().ToString();

        base.Render(writer); // comment out to not render
    }
}

and then on the html side it'd look like this

<app:TestControl runat="server">
    <html>
     <strong>hi there...</strong>
    </html>
</app:TestControl>
Brian Surowiec
This is exactly what I was trying to do after reading Martin's answer. This worked perfectly. Thanks.
Max Schmeling
You might need to mess around with some of the settings for the control object. Not sure if the contents will be added to the viewstate here, but if so you may want to disable that. The same goes for auto creating ClientIds. Maybe create a custom control derived from Control that removes those things so all you get is strait up html rendering.
Brian Surowiec
A: 

The easiest way is to simply use what already exists:

<asp:Literal runat="server" ID="myHtmlControl">
    <div>
        <span>Some Text</span>
        <button>Do Something</button>
    </div>
</asp:Literal>

Works like a charm!

The only difference with your question is, that the contents is stored in the property named Text, rather than Html. Can you live with that?

Otherwise, you can use a re-implementation of Literal like this one:

[DefaultProperty("Html")]
[ParseChildren(false)]
public class CustomHtmlControl : WebControl
{
    [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    [DefaultValue("")]
    public string Html
    { 
        get
        {
            return this.ViewState["Html"] as string ?? "";
        }
        set
        {
            if (this.HasControls())
                this.Controls.Clear();
            this.ViewState["Html"] = value;
        }
    }

    protected override void AddParsedSubObject(object obj)
    {
        if (obj is LiteralControl)
            this.Html = ((LiteralControl) obj).Text;
        else
             throw new NotSupportedException("Cannot add child controls to CustomHtmlControl.");
    }

    protected override void RenderContents(HtmlTextWriter writer)
    {
        writer.Write(this.Html);
    }
}
Ruben
At first thought I don't really like the idea of inheriting from a class to basically override all of its functionality and make it something completely different. What does everyone else think? This is, if nothing else, a clever solution.
Max Schmeling
Note that this sample implementation does not override any functionality as such. It's *like* `Literal`, but it's implementation is it's own: it directly inherits from `WebControl`. Or am I misunderstanding your comment?
Ruben