1

how can i create a custom control that accepts a inner html, like the usual .net datagrid or ajax tabbed control... something like this:

<KITT:tabs id="s" runat="server" >
 <w:tab sectionid="benefits">
here goes my html or any content, i want to render as is
 </w:tab>
</KITT:tabs>

I know how to create that with no inner html, a Tab object, a list of Tabs, then using

[ParseChildren(true,"MyTabs")]

in the control... but i dont know where to go from there, any hints?

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
Ayyash
  • 4,257
  • 9
  • 39
  • 58

3 Answers3

2

This is the strategy I use, which I think is the easiest. This one is a Panel (which is rendered as a div), and is a server control (no ascx):

public class Tab : Panel {

    private Literal InnerHtmlLiteral { get; set; }

    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("")]
    [Localizable(true)]
    [PersistenceMode(PersistenceMode.InnerDefaultProperty)] // this is the significant attribute.
    public string InnerHtml {
        get { return InnerHtmlLiteral.Text; }
        set { InnerHtmlLiteral.Text = value; }
    }

    public Tab() {
        InnerHtmlLiteral = new Literal();
    }

    protected override void OnInit(EventArgs e) {
        base.OnInit(e);
        Controls.Add(InnerHtmlLiteral);
        InnerHtmlLiteral.ID = ID + "_InnerHtml";
    }
}

No messing around with templates, and very few special attributes needed in order to make it work. I'm just using a string as the property and then rendering it using a Literal control.

kad81
  • 10,712
  • 3
  • 38
  • 44
1

combining the answer about custom controls in general: custome child controls

and MSDN Templated Conrols

the right way to go about this is very simple, once creating and defining the child element in a namespace (because you need to cross reference it), it should have one added property: the Tab class looks like this

namespace MyNS.Content {
public class Tab : System.Web.UI.UserControl
{

    private string _title;

    public Tab()
        : this(String.Empty)
    {
    }

    public Tab(string title)
    {
        _title = title;
    }

    public string Title
    {
        get { return _title; }
        set { _title = value; }
    }

    private ITemplate tabContent = null;
    [
    TemplateContainer(typeof(TemplateControl)),
    PersistenceMode(PersistenceMode.InnerProperty),
    TemplateInstance(TemplateInstance.Single),
    ]
    public ITemplate TabContent
    {
        get
        {
            return tabContent;
        }
        set
        {
            tabContent = value;
        }
    }

}
}

This will allow the tabcontent child to your main tag

in your control ascx create the necessary [ParseChildren(true, "MyTabs")] and bind your MyTabs list or collection to a repeater, this will output all contained tabs, your ascx looks like this

<asp:repeater id="rpContent" runat="server" onitemdatabound="rpContent_itemdatabound">
<itemtemplate>
    <asp:hyperlink id="hlHeader" runat="server" navigateurl="javascript://"></asp:hyperlink>

        <div>
            <asp:placeholder id="plTabContent" runat="server"></asp:placeholder>
        </div>

</itemtemplate>

the code behind looks like this

[ParseChildren(true, "MyTabs")]
public partial class KITT_controls_tabgroup : System.Web.UI.UserControl
{
    private List<Tab> _myTabs;
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public List<Tab> MyTabs
    {
        get
        {
            if (_myTabs == null)
            {
                _myTabs = new List<Tab>();
            }
            return _myTabs;
        }

    }

    protected void Page_Load(object sender, EventArgs e)
    {
        rpContent.DataSource = MyTabs;
        rpContent.DataBind();

    }
    protected void rpContent_itemdatabound(Object Sender, RepeaterItemEventArgs e)
    {

        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            Tab i = e.Item.DataItem as Tab;
            i.TabContent.InstantiateIn(((PlaceHolder)e.Item.FindControl("plTabContent")));

            ((HyperLink)e.Item.FindControl("hlHeader")).Text = i.Title;
        }
    }
}

finally, register your controls (both Tab and ascx)

<add tagPrefix="w" namespace="MyNS.Content" />
<add tagPrefix="KITT" tagName="TabbedContent" src="~/controls/tabbedcontent.ascx"/>

and use it...

 <kitt:tabbedcontent id="upgradedesktop" runat="server">
    <w:Tab  title="Overview" isdefault="true" runat="server">
        <TabContent>
            your html tags and server side tags here
        </TabContent>
    </w:Tab>
    <w:tab title="Benefits" runat="server" >
        <tabcontent>
            your html tags and server side tags here
        </tabcontent>
    </w:tab>
    <w:tab title="Products" runat="server">
        <tabcontent>
            your html tags and server side tags here
        </tabcontent>
    </w:tab>
</kitt:tabbedcontent>
Community
  • 1
  • 1
Ayyash
  • 4,257
  • 9
  • 39
  • 58
0

What you're looking for is called a "templated control." You can find more information on MSDN.

Community
  • 1
  • 1
Adam Maras
  • 26,269
  • 6
  • 65
  • 91
  • 1
    on second thought, its not, i dont want to bind the tabs as in templated control, i want to display whatever is there inside, but mind you, the there might me multiple tabs, it looks like two seperate controls now, but im gonna look further for this one – Ayyash Oct 28 '09 at 22:02