Search code examples
c#asp.netmenucustom-controlscustom-server-controls

Providing Declarative data for controls


I am in the process of learning Server Controls Development and looking for proper instructions to enable setting the data declaratively through source. For example the dropdownlist control provides declarative data like below

<asp:DropDownList id="dropdown" runat="server">
    <asp:ListItem text="Project Initiation" value="1"></asp:ListItem>
    <asp:ListItem text="Documentation" value="2"></asp:ListItem>
</asp:DropDownList>

similarly i am looking for declaratively providing data to my simple menu control that displays image surrounded by image like below (the output markup) from a datasource

<a>
 <img src="" />
</a>

Please do not point me to a link, the least anyone can do is that. I would like a clear explanation of what needs to be done for providing such functionality. I would like my final source to look like below

<asp:sidebar runat="server" id="sb">
 <asp:sidebaritem navigateurl="" imageurl="" label=""></asp:sidebaritem>
</asp:sidebar>

sidebar item class is defined below and i have a property too

class

public class SidebarItem
 {
   private string _navigateUrl;

   public string NavigateUrl
    {
       get { return _navigateUrl; }
       set { _navigateUrl = value; }
    }
    . . . 
 }

property

[PersistenceMode(PersistenceMode.InnerProperty)]
[NotifyParentProperty(true)]
public ICollection<SidebarItem> Items
{
    get { return _sidebarItems; }
    set { _sidebarItems = value; }
}

Solution

  • The answer you are looking for is here: http://msdn.microsoft.com/en-us/library/9txe1d4x.aspx
    As you've asked for more than just a link, here's an example solution specific to your scenario:

    [
    AspNetHostingPermission(SecurityAction.Demand,
        Level = AspNetHostingPermissionLevel.Minimal),
    AspNetHostingPermission(SecurityAction.InheritanceDemand,
        Level = AspNetHostingPermissionLevel.Minimal),
    DefaultProperty("Items"),
    ParseChildren(true, "Items"),
    ToolboxData("<{0}:SideBar runat=\"server\"> </{0}:SideBar>")
    ]
    public class SideBar : WebControl
    {
        private ArrayList itemsList;
    
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        //[Editor(typeof(ContactCollectionEditor), typeof(UITypeEditor))]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public ArrayList Items
        {
            get
            {
                if (itemsList == null)
                {
                    itemsList = new ArrayList();
                }
                return itemsList;
            }
        }
    
        protected override void RenderContents(HtmlTextWriter writer)
        {
            writer.RenderBeginTag(HtmlTextWriterTag.Ul);
            foreach (object o in itemsList)
            {
                SideBarItem item = (SideBarItem)o;
                writer.RenderBeginTag(HtmlTextWriterTag.Li);
                writer.AddAttribute(HtmlTextWriterAttribute.Href, item.NavigateUrl);
                writer.RenderBeginTag(HtmlTextWriterTag.A);
                writer.AddAttribute(HtmlTextWriterAttribute.Src, item.ImageUrl);
                writer.RenderBeginTag(HtmlTextWriterTag.Img);
                writer.RenderEndTag(); // Img
                writer.RenderEndTag(); // A
                writer.RenderEndTag(); // Li
            }
            writer.RenderEndTag(); // Ul
        }
    }
    
    
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class SideBarItem
    {
        public SideBarItem()
            : this(String.Empty, String.Empty, String.Empty)
        {
        }
    
        public SideBarItem(string imgUrl, string navUrl, string label)
        {
            ImageUrl = imgUrl;
            NavigateUrl = navUrl;
            Label = label;
        }
    
        [DefaultValue("")]
        [NotifyParentProperty(true)]
        public String ImageUrl { get; set; }
    
        [DefaultValue("")]
        [NotifyParentProperty(true)]
        public String NavigateUrl { get; set; }
    
        [DefaultValue("")]
        [NotifyParentProperty(true)]
        public String Label { get; set; }
    }
    

    Then in the ASPX file would be as such:
    Referenced

    <%@ Register Assembly="MyProject" Namespace="MyProject" TagPrefix="cc1" %>
    

    Implemented

        <cc1:SideBar ID="SideBar1" runat="server">
            <cc1:SideBarItem ImageUrl="#" NavigateUrl="#" />
            <cc1:SideBarItem ImageUrl="#" NavigateUrl="#" />
        </cc1:SideBar>