Is there a way to put inner controls inside a ASP.NET Custom Control?
Asked Answered
B

3

9

I want to do something like (Updated example):

<uc:Tabs>
  <Tab Name="A handy tab">
    <Node Url="~/Default.aspx" />
    <Node Url="~/Node2.aspx" />
  </Tab>      
  <Tab Name="Another handy tab">
    <Node Url="~/Neato.aspx" />
    <Node Url="~/Node3.aspx" />
    <Node Url="~/Node4.aspx" />
  </Tab>
<uc:Tabs>

Possible? Any tutorials or how-to's? I'm not sure what to even search on or what this is called so haven't found anything so far. Inner controls? Inner collection something something...?

British answered 3/3, 2009 at 0:15 Comment(0)
M
15

Use the ParseChildrenAttribute and PersistChildrenAttribute attributes:

[ParseChildren(false)]
[PersistChildren(true)]
public class MyControl : UserControl { }

This will cause any controls you put inside the reference:

<uc:MyControl runat="server">
  <asp:TextBox runat="server" />
<uc:MyControl>

To be appended to the end of the Controls collection of your UserControl contents.

However, if you want to have a collection of controls, you should probably use a server control and not a user control. For a control that works like this:

<foo:TabControl runat="server">
    <Tabs>
        <foo:Tab CssClass="myclass" Title="Hello World" />
    </Tabs>
</foo:TabControl>

You need a Control class that has a Tabs property; the Tabs property should be a Collection; and it should contain objects of type Tab. I've created the three classes here:

[ParseChildren(true, "Tabs")]
public class TabControl: WebControl, INamingContainer
{
    private TabCollection _tabs;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
    public TabCollection Tabs
    {
        get
        {
            if (_tabs == null)
            {
                _tabs = new TabCollection();
            }
            return _tabs;
        }
    }

    protected override void Render(HtmlTextWriter writer)
    {
        foreach (Tab tab in Tabs)
        {
            writer.WriteBeginTag("div");
            writer.WriteAttribute("class", tab.CssClass);
            writer.Write(HtmlTextWriter.TagRightChar);
            writer.Write("this is a tab called " + tab.Title);
            writer.WriteEndTag("div");
        }
    }
}

And the tab class:

public class Tab
{
    public string CssClass { get; set; }
    public string Title { get; set; }
}

And the tab collection:

public class TabCollection : Collection<Tab> { }
Made answered 3/3, 2009 at 0:19 Comment(1)
I'll give this a whirl. I'm using a custom (server?) control right now; I think the "uc" might have led you to believe it was a user control.British
B
3

Follow up

Rex M provided the answer but just wanted to follow up on what I've also found for posterity.

It seems like you can do either:

<ui:Tabs runat="server">
    <ui:Tab TabText="Blah">
        <ui:Node Url="~/Default.aspx" />
        <ui:Node Url="~/More.aspx" />
        <ui:Node Url="~/Another.aspx" />
    </ui:Tab>
    <ui:Tab TabText="Nanner">
        <ui:Node Url="~/Default.aspx" />
        <ui:Node Url="~/More.aspx" />
        <ui:Node Url="~/Another.aspx" />
    </ui:Tab>
    <ui:Tab TabText="High There">
        <ui:Node Url="~/Default.aspx" />
        <ui:Node Url="~/More.aspx" />
        <ui:Node Url="~/Another.aspx" />
    </ui:Tab>
</ui:Tabs>

OR

<ui:Tabs runat="server">
    <TabItems>
        <ui:Tab InnerHeading="Big Huge Heading" TabText="Big">
            <NodeItems>
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
            </NodeItems>
        </ui:Tab>
    </TabItems>
    <TabItems>
        <ui:Tab InnerHeading="Hi ya" TabText="Hi">
            <NodeItems>
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
                <ui:Node Url="~/Default.aspx" />
            </NodeItems>
        </ui:Tab>
    </TabItems>
</ui:Tabs>

Then within code:

namespace Controls
{
    [ToolboxData("<{0}:Tabs runat=server></{0}:Tabs>"), ParseChildren(true, "TabItems")]
    public class Tabs : BaseControl, INamingContainer
    {
        private TabCollection tabItems;
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public TabCollection TabItems
        {
            get
            {
                if (tabItems == null) 
                { 
                    tabItems = new TabCollection(); 
                } 
                return tabItems;
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write("<div id=\"tabs\" class=\"pane\" style=\"display: none\"><ul>");
            int tabNumber = 1;
            foreach (Tab tab in TabItems)
            {
                string li = string.Format("<li id=\"tab_{0}\"><a href=\"#tab{0}\"><span>{1}</span></a></li>", tabNumber, tab.TabText);
                tabNumber++;
                writer.Write(li);
            }
            writer.Write("</ul>");
            tabNumber = 1;
            foreach (Tab tab in TabItems)
            {
                string div = string.Format("<div id=\"tab{0}\" class=\"pane\"><h1>{1}</h1>", tabNumber, tab.InnerHeading);
                tabNumber++;
                writer.Write(div);
                foreach (Node node in tab.NodeItems)
                {
                    string a = string.Format("<a href='{0}'>{1}</a>", node.Url, "Text holder");
                    writer.Write(a);
                }
                writer.Write("</div>");
            }
            writer.Write("</div>");
        }
    }

    public class TabCollection : List<Tab> { }

    [ParseChildren(true, "NodeItems")]
    public class Tab
    {
        private string tabText = string.Empty;
        private string innerHeading = string.Empty;
        private string showOn = string.Empty;
        public string TabText
        {
            get { return tabText; }
            set { tabText = value; }
        }
        public string InnerHeading
        {
            get { return innerHeading; }
            set { innerHeading = value; }
        }

        public string ShowOn
        {
            get { return showOn; }
            set { showOn = value; }
        }

        private NodeCollection nodeItems;
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public NodeCollection NodeItems
        {
            get
            {
                if (nodeItems == null)
                {
                    nodeItems = new NodeCollection();
                }
                return nodeItems;
            }
        }
    }

    public class NodeCollection : List<Node> { }

    public class Node
    {
        private string url = string.Empty;
        public string Url
        {
            get { return url; }
            set { url = value; }
        }
    }
}

This will obviously be changing (mine's going to be reading from the web.sitemap among other changes), but this should get anyone with the same needs well under their way.

British answered 3/3, 2009 at 16:58 Comment(0)
Z
0
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Web.UI.HtmlControls;

namespace Gui.Controls
{

    [DefaultProperty("Text")]
    [ToolboxData("<{0}:GPMenu runat=server></{0}:GPMenu>")]
    [ParseChildren(false)]
    public class GPMenu : WebControl
    {

        private void CreateDynamicControls()
        {
            //some code for Creating Dynamic Controls 


        } //eof method 

        #region FieldsAndProps

        #region ActiveTab

        protected int _ActiveTab;
        [Bindable(true)]
        [Category("Appearance")]
        public int ActiveTab // Public properties   
        {
            get { return _ActiveTab; }
            set { _ActiveTab = value; }
        }
        #endregion ActiveTab

        #region Caption

        protected string _Caption = "";
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string Caption // Public properties  
        {
            get { return _Caption; }
            set { _Caption = value; }
        }
        #endregion Caption

        #region MenuId

        protected string _MenuId = "0";
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string MenuId // Public properties   
        {
            get { return _MenuId; }
            set { _MenuId = value; }
        }
        #endregion MenuId

        #region Text

        protected string _Text = "";
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string Text // Public properties 
        {
            get { return _Text; }
            set { _Text = value; }
        }
        #endregion Text

        #region UserObj

        private FB.User userObj;
        public FB.User UserObj
        {
            get
            {
                return userObj;
            } //eof get 
            set
            {
                userObj = value;

            } //eof set 

        } //eof prop 

        #endregion UserObj

        #region ListTabWizard


        private List<App.Models.TabWizard> _ListWizard;

        [Bindable(true)]
        [Category("Appearance")]
        [Description(" The data structure used for databinding the menu ")]
        public List<App.Models.TabWizard> ListWizard
        {
            get { return _ListWizard; }
            set { _ListWizard = value; }
        }

        #endregion ListWizard

        #endregion FieldsAndProps

        #region Constructors
        public GPMenu()
        {
            //Statement to run while initialize of control  
        }
        #endregion Constructors

        #region Overrides

        public override void RenderControl(HtmlTextWriter writer)
        {
            RenderContents(writer);
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            //Codes for rendering html to be written here   
            output.WriteBeginTag("div");
            output.WriteAttribute("class", _Caption);
            output.WriteAttribute("ID", this.ID);
            RenderChildren(output); // Render Child Control is Exists   
            output.WriteEndTag("div");
        }

        public override void DataBind()
        {
            this.Controls.Clear();
            base.DataBind();

            #region Debug

            //old configure the logger
            //logger.Debug("Custom GPMenu DataBind called ");

            #endregion Debug

            #region AddTheTopDiv

            Panel panTabMenuTop = new Panel();
            panTabMenuTop.ID = "panTabMenuTop";
            panTabMenuTop.CssClass = "CssClassPanTabMenuTop";
            this.Controls.Add(panTabMenuTop);

            #endregion AddTheTopDiv

            #region AddTheUlOpenTag

            HtmlGenericControl conGenUi = new HtmlGenericControl("ul");
            conGenUi.ID = "paakallo";



            #endregion AddTheUlOpenTag


            #region ForEachMenuItemInTheListAddTheLinks

            if (this.ListWizard == null)
                throw new Exception(" The List of menu items is null for " + this.ID);



            #region ForEachWizardItem

            for (int iListMenuItem = 0; iListMenuItem < this.ListWizard.Count; iListMenuItem++)
            {
                App.Models.TabWizard objMenuItem = this.ListWizard[iListMenuItem];

                #region AddTheLiOpenTag

                PlaceHolder objPlaceHolderLiOpen = new PlaceHolder();
                objPlaceHolderLiOpen.Controls.Add(new LiteralControl("<li>"));
                conGenUi.Controls.Add(objPlaceHolderLiOpen);

                #endregion AddTheLiOpenTag

                #region BuildTheLocalizedLink

                #region Check that the whole MenuItem data structure is not null

                if (objMenuItem == null)
                    throw new Exception(
                        "The building of the GPMenu failed since \n: " +
                        " null MenuItem at  " + iListMenuItem.ToString() + " for " + this.ID);

                #endregion Check that the whole MenuItem data structure is not null

                //the variant with LinkButton does PostBack == BAD !!!                
                PlaceHolder objPlaceHolderLink = new PlaceHolder();

                #region BuildTheLinkId_with_MenuItemId

                if (String.IsNullOrEmpty(objMenuItem.Link_Id.ToString()))
                {
                    throw new Exception(
                        "The building of the GPMenu failed since \n: " +
                        " null or empty MenuItemId for  " + iListMenuItem.ToString() + " for " + this.ID);
                }

                #endregion BuildTheLinkId_with_MenuItemId

                #region AddTheTextForTheLink_with_GuiPageLinkURL

                //check that this LinkItem points to a registered page 
                if (objMenuItem.Link_Id == null)
                {
                    throw new Exception(
                        "The building of the GPMenu failed since \n: " +
                        " null GuiPage for " + iListMenuItem.ToString() + " for " + this.ID);
                }

                string strActiveLinkCssClass = String.Empty;

                string strTabTxt = String.Empty;
                try
                {
                    strTabTxt = objMenuItem.TabTitle;
                }
                catch (System.Exception ex)
                {
                    continue;
                }

                #region BuildTheActualLink


                string strLinkTxt = String.Empty;
                strLinkTxt += "<a " + strActiveLinkCssClass + " href=\"";
                string strLinkUrl = Http.UrlHandler.ExpandUrl(objMenuItem.LinkURL);


                #endregion BuildTheActualLinks

                #region AddTheColorForTheLinkAndRemoveTheBorderOfActiveTab

                if (this.ActiveTab != null && strLinkUrl.Contains("tabid=" + this.ActiveTab.ToString()))
                    strActiveLinkCssClass = "class=\"CssClassGPMenuActiveLink\"";

                #endregion AddTheColorForTheLinkAndRemoveTheBorderOfActiveTab

                strLinkTxt += strLinkUrl + "\"" + strActiveLinkCssClass;

                #endregion AddTheTextForTheLink_with_GuiPageLinkURL

                #region AddTheToolTip



                string strVisibleToolTipTxt = String.Empty;
                try
                {
                    strVisibleToolTipTxt = objMenuItem.ItemButtonToolTip;
                }
                catch (System.Exception ex)
                {
                    continue;
                }



                strLinkTxt += "\" title=\"" + strVisibleToolTipTxt +
                    "\"><span>" + strTabTxt + "</span></a>";

                #endregion AddTheToolTip

                #region AddTheLabel_used_in_The_TabMenu

                objPlaceHolderLink.Controls.Add(new LiteralControl(strLinkTxt));
                conGenUi.Controls.Add(objPlaceHolderLink);

                #endregion AddTheLabel_used_in_The_TabMenu

                #endregion BuildTheLocalizedLink

                #region AddTheLiCloseTag

                PlaceHolder objPlaceHolderLiClose = new PlaceHolder();
                objPlaceHolderLiClose.Controls.Add(new LiteralControl("</li>"));
                conGenUi.Controls.Add(objPlaceHolderLiClose);

                #endregion AddTheLiCloseTag

            } //eof foreach MenuItem in List
            #endregion ForEachWizardItem

            #endregion ForEachMenuItemInTheListAddTheLinks

            #region AddTheUlCloseTag

            this.Controls.Add(conGenUi);

            #region AddTheBottomDiv

            Panel panTabMenuBottom = new Panel();
            panTabMenuBottom.ID = "panTabMenuBottom";
            panTabMenuBottom.CssClass = "CssClassPanTabMenuBottom";
            this.Controls.Add(panTabMenuBottom);

            #endregion AddTheBottomDiv

            #endregion AddTheUlCloseTag

        } //eof method 

        #region TemplateMethods
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
        } //eof method

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            this.CreateDynamicControls();
        } //eof method 


        protected override object SaveViewState()
        {
            return new Pair(base.SaveViewState(), null);
        } //eof method 

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(((Pair)savedState).First);
            EnsureChildControls();
        } //eof method 


        #endregion TemplateMethods


        #endregion Overrides

    } //eof class 
} //eof namespace 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Collections.Specialized;


namespace App.Models
{
    /// <summary>
    /// Serves as the model for  the tabwizard page 
    /// </summary>
    public class TabWizard
    {
        #region Properties

        #region TabWizardId

        public long tbGuiTabWizardId { get; set; }


        #endregion TabWizardId


        #region TabId

        public int TabId { get; set; }

        #endregion TabId

        #region Link_Id

        public int Link_Id { get; set; }

        #endregion Link_Id

        #region WizardId

        public int WizardId { get; set; }

        #endregion WizardId

        #region TabOrder

        public int TabOrder { get; set; }

        #endregion TabOrder

        #region TabTitle

        public string TabTitle { get; set; }

        #endregion TabTitle

        #region TabHasManyButtons

        public bool TabHasManyButtons { get; set; }

        #endregion TabHasManyButtons

        #region ButtonTitle

        public string ButtonTitle { get; set; }

        #endregion ButtonTitle

        #region Description

        public string Description { get; set; }

        #endregion Description

        #region ProcToStart

        public string ProcToStart { get; set; }

        #endregion ProcToStart

        #region ProcId

        public string ProcId { get; set; }

        #endregion ProcId

        #region ItemMetaId

        public string ItemMetaId { get; set; }

        #endregion ItemMetaId

        #region ItemId

        public string ItemId { get; set; }

        #endregion ItemId

        #region ItemStartProc

        public string ItemStartProc { get; set; }

        #endregion ItemStartProc

        #region ItemButtonToolTip

        public string ItemButtonToolTip { get; set; }

        #endregion ItemButtonToolTip

        #region ItemButtonText

        public string ItemButtonText { get; set; }

        #endregion ItemButtonText

        #region TypeOfTab

        public string TypeOfTab { get; set; }

        #endregion TypeOfTab

        #region WizardHasStepping

        public bool WizardHasStepping { get; set; }

        #endregion WizardHasStepping

        #region RunProcOnTabClick

        public bool RunProcOnTabClick { get; set; }

        #endregion RunProcOnTabClick

        #region TabIsPRS

        public bool TabIsPRS { get; set; }

        #endregion TabIsPRS

        #region ItemIsPRS

        public bool ItemIsPRS { get; set; }

        #endregion ItemIsPRS

        #region FlagPresentAreYouSurePrompt

        public bool FlagPresentAreYouSurePrompt { get; set; }

        #endregion FlagPresentAreYouSurePrompt

        #region PromptAreYouSureText

        public string PromptAreYouSureText { get; set; }

        #endregion PromptAreYouSureText

        #region PageId

        public int PageId { get; set; }

        #endregion PageId

        #region MenuId

        public int MenuId { get; set; }

        #endregion MenuId


        #endregion Properties

        #region Props


        #region Constructor


        public TabWizard(System.Data.DataRow dr)
        {
            if (dr["tbGuiTabWizardId"] != null && !(dr["tbGuiTabWizardId"] is DBNull))
                this.tbGuiTabWizardId = System.Convert.ToInt64(dr["tbGuiTabWizardId"]);


            if (dr["TabId"] != null && !(dr["TabId"] is DBNull))
                this.TabId = System.Convert.ToInt32(dr["TabId"]);


            if (dr["Link_Id"] != null && !(dr["Link_Id"] is DBNull))
                this.Link_Id = System.Convert.ToInt32(dr["Link_Id"]);


            if (dr["WizardId"] != null && !(dr["WizardId"] is DBNull))
                this.WizardId = System.Convert.ToInt32(dr["WizardId"]);


            if (dr["TabOrder"] != null && !(dr["TabOrder"] is DBNull))
                this.TabOrder = System.Convert.ToInt32(dr["TabOrder"]);


            if (dr["TabTitle"] != null && !(dr["TabTitle"] is DBNull))
                this.TabTitle = System.Convert.ToString(dr["TabTitle"]);


            if (dr["TabHasManyButtons"] != null && !(dr["TabHasManyButtons"] is DBNull))
                this.TabHasManyButtons = System.Convert.ToBoolean(dr["TabHasManyButtons"]);


            if (dr["ButtonTitle"] != null && !(dr["ButtonTitle"] is DBNull))
                this.ButtonTitle = System.Convert.ToString(dr["ButtonTitle"]);


            if (dr["Description"] != null && !(dr["Description"] is DBNull))
                this.Description = System.Convert.ToString(dr["Description"]);


            if (dr["ProcToStart"] != null && !(dr["ProcToStart"] is DBNull))
                this.ProcToStart = System.Convert.ToString(dr["ProcToStart"]);


            if (dr["ProcId"] != null && !(dr["ProcId"] is DBNull))
                this.ProcId = System.Convert.ToString(dr["ProcId"]);


            if (dr["ItemMetaId"] != null && !(dr["ItemMetaId"] is DBNull))
                this.ItemMetaId = System.Convert.ToString(dr["ItemMetaId"]);


            if (dr["ItemStartProc"] != null && !(dr["ItemStartProc"] is DBNull))
                this.ItemStartProc = System.Convert.ToString(dr["ItemStartProc"]);


            if (dr["ItemButtonToolTip"] != null && !(dr["ItemButtonToolTip"] is DBNull))
                this.ItemButtonToolTip = System.Convert.ToString(dr["ItemButtonToolTip"]);


            if (dr["ItemButtonText"] != null && !(dr["ItemButtonText"] is DBNull))
                this.ItemButtonText = System.Convert.ToString(dr["ItemButtonText"]);


            if (dr["TypeOfTab"] != null && !(dr["TypeOfTab"] is DBNull))
                this.TypeOfTab = System.Convert.ToString(dr["TypeOfTab"]);


            if (dr["WizardHasStepping"] != null && !(dr["WizardHasStepping"] is DBNull))
                this.WizardHasStepping = System.Convert.ToBoolean(dr["WizardHasStepping"]);


            if (dr["RunProcOnTabClick"] != null && !(dr["RunProcOnTabClick"] is DBNull))
                this.RunProcOnTabClick = System.Convert.ToBoolean(dr["RunProcOnTabClick"]);


            if (dr["TabIsPRS"] != null && !(dr["TabIsPRS"] is DBNull))
                this.TabIsPRS = System.Convert.ToBoolean(dr["TabIsPRS"]);


            if (dr["ItemIsPRS"] != null && !(dr["ItemIsPRS"] is DBNull))
                this.ItemIsPRS = System.Convert.ToBoolean(dr["ItemIsPRS"]);


            if (dr["FlagPresentAreYouSurePrompt"] != null && !(dr["FlagPresentAreYouSurePrompt"] is DBNull))
                this.FlagPresentAreYouSurePrompt = System.Convert.ToBoolean(dr["FlagPresentAreYouSurePrompt"]);


            if (dr["PromptAreYouSureText"] != null && !(dr["PromptAreYouSureText"] is DBNull))
                this.PromptAreYouSureText = System.Convert.ToString(dr["PromptAreYouSureText"]);


            if (dr["PageId"] != null && !(dr["PageId"] is DBNull))
                this.PageId = System.Convert.ToInt32(dr["PageId"]);


            if (dr["LinkURL"] != null && !(dr["LinkURL"] is DBNull))
                this.LinkURL = System.Convert.ToString(dr["LinkURL"]);



            if (dr["MenuId"] != null && !(dr["MenuId"] is DBNull))
                this.MenuId = System.Convert.ToInt16(dr["MenuId"]);


        } //eof constructor  

        #endregion Constructor







        #region LinkURL

        private string _LinkURL = String.Empty;
        public string LinkURL
        {
            get { return _LinkURL; }
            set { _LinkURL = value; }
        }

        #endregion LinkURL


        #endregion Props



    } //eof class 
} //eof namespace 
Zedoary answered 15/2, 2010 at 19:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.