views:

644

answers:

3

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...?

+7  A: 

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");
        }
    }
}

public class TabCollection : Collection<Tab> { }

public class Tab
{
    public string CssClass { get; set; }
    public string Title { get; set; }
}
Rex M
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.
rball
+3  A: 

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.

rball
A: 
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 
YordanGeorgiev