How to: Use Services and Action Lists with Control Designers

The following code example illustrates a set of custom ASP.NET controls with associated control designers. The control designers show how to implement editable regions and action lists, and how to interact with host services.

This example is described in detail in Sample Control Designer with Action Lists and Services.

Example

<?xml version="1.0" encoding="utf-8" ?>
<styles>
    <style name="BackColor" value="red"></style>
    <style name="ForeColor" value="white"></style>
</styles>

<?xml version="1.0" encoding="utf-8" ?>
<styles>
    <style name="BackColor" value="blue"></style>
    <style name="ForeColor" value="white"></style>
</styles>

<?xml version="1.0" encoding="utf-8" ?>
<styles>
    <style name="BackColor" value="green"></style>
    <style name="ForeColor" value="white"></style>
</styles>
<%@ page language="VB" %>
<%@ register tagprefix="aspSample" 
    assembly="DesignerServicesAndListsVB" 
    namespace="Samples.AspNet.VB.Controls" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">
    <title>Designer Samples</title>
</head>

<body>
  <form id="form1" runat="server">
      <p style="font-family:tahoma;font-size:larger;
      font-weight:bold">
        Using Action Lists and Designer Host Services</p>
      <div style="font-family:tahoma;font-size:x-small">
        <span style="font-size: 10pt">Control #1 (ControlWithStyleTasksDesigner):
        PanelContainerDesigner using a DesignerActionList, which
        obtains a list of XML files in the project and sets 
        the style using the XML element
        definitions.</span><p />
      </div>
      <aspSample:ControlWithStyleTasks id="ctl1" 
        runat="server" 
        backcolor="Red" forecolor="White">
          Hello there.</aspSample:ControlWithStyleTasks>
      <br />
      <div style="font-family:tahoma;font-size:x-small">
        <span style="font-size: 10pt">Control #2 (ControlWithConfigurationSettingDesigner):
        PanelContainerDesigner using configuration settings
        to obtain 
        the FrameCaption value.</span><p />
      </div>
      <aspSample:ControlWithConfigurationSetting 
        id="ctl2" runat="server">
        Hello There
      </aspSample:ControlWithConfigurationSetting>
      <br />
      <div style="font-family:tahoma;font-size:x-small">
        <span style="font-size: 10pt">Control #3 (ControlWithButtonTasksDesigner):
        PanelContainerDesigner using a smart-task action 
        item to insert a new button to the Web Form.</span><p />
      </div>
      <aspSample:ControlWithButtonTasks 
        id="ctl3" runat="server">
        Hello There
      </aspSample:ControlWithButtonTasks>
      &nbsp; &nbsp;
  </form>
</body>
</html>
<%@ page language="C#" %>
<%@ register tagprefix="aspSample" 
    assembly="DesignerServicesAndListsCS" 
    namespace="Samples.AspNet.CS.Controls" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">
    <title>Designer Samples</title>
</head>

<body>
  <form id="form1" runat="server">
      <p style="font-family:tahoma;font-size:larger;
      font-weight:bold">
        Using Action Lists and Designer Host Services</p>
      <div style="font-family:tahoma;font-size:x-small">
        <span style="font-size: 10pt">Control #1 (ControlWithStyleTasksDesigner):
        PanelContainerDesigner using a DesignerActionList, which
        obtains a list of XML files in the project and sets 
        the style using the XML element
        definitions.</span><p />
      </div>
      <aspSample:ControlWithStyleTasks id="ctl1" 
        runat="server" 
        backcolor="Red" forecolor="White">
          Hello there.</aspSample:ControlWithStyleTasks>
      <br />
      <div style="font-family:tahoma;font-size:x-small">
        <span style="font-size: 10pt">Control #2 (ControlWithConfigurationSettingDesigner):
        PanelContainerDesigner using configuration settings
        to obtain 
        the FrameCaption value.</span><p />
      </div>
      <aspSample:ControlWithConfigurationSetting 
        id="ctl2" runat="server">
        Hello There
      </aspSample:ControlWithConfigurationSetting>
      <br />
      <div style="font-family:tahoma;font-size:x-small">
        <span style="font-size: 10pt">Control #3 (ControlWithButtonTasksDesigner):
        PanelContainerDesigner using a smart-task action 
        item to insert a new button to the Web Form.</span><p />
      </div>
      <aspSample:ControlWithButtonTasks 
        id="ctl3" runat="server">
        Hello There
      </aspSample:ControlWithButtonTasks>
      &nbsp; &nbsp;
  </form>
</body>
</html>
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Diagnostics
Imports System.Drawing
Imports System.IO
Imports System.Text
Imports System.Web.UI
Imports System.Web.UI.Design
Imports System.Web.UI.Design.WebControls
Imports System.Web.UI.WebControls
Imports System.Reflection
Imports System.Xml
Imports System.Configuration

Namespace Samples.AspNet.VB.Controls

    ' This region-based control renders the content of an XML file.
    <Designer(GetType(ControlWithStyleTasksDesigner))> _
    <ToolboxData("<{0}:ControlWithStyleTasks runat=server>" _
                 & "</{0}:ControlWithStyleTasks>")> _
    Public Class ControlWithStyleTasks
        Inherits Panel
    End Class

    <Designer(GetType(ControlWithConfigurationSettingDesigner))> _
    <ToolboxData("<{0}:ControlWithConfigurationSetting runat=server " _
                 & "width=100%></{0}:ControlWithConfigurationSetting>")> _
    Public Class ControlWithConfigurationSetting
        Inherits Panel
    End Class

    <Designer(GetType(ControlWithButtonTasksDesigner))> _
    <ToolboxData("<{0}:ControlWithButtonTasks runat=server " _
                 & "width=100%></{0}:ControlWithButtonTasks>")> _
    Public Class ControlWithButtonTasks
        Inherits Panel
    End Class 

    ' Declare a custom button to add dynamically at design time. 
    Public Class NewButton
        Inherits Button

        Public Sub New()
            [Text] = "NewButton" 
        End Sub 
    End Class 

    ' This control designer is used to read xml files from the project.
    <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
    Public Class ControlWithStyleTasksDesigner
        Inherits PanelContainerDesigner
        Private _style As Style = Nothing 

        ' Add the caption by default. Note that the caption will  
        ' only appear if the Web server control allows  
        ' child controls rather than properties.  
        Public Overrides ReadOnly Property FrameCaption() _
          As String 

            Get 
                Return "Container getting styles from the project item." 
            End Get 
        End Property 

        Public Overrides ReadOnly Property FrameStyle() As Style
            Get 
                If _style Is Nothing Then
                    _style = New Style()
                    _style.Font.Name = "Verdana"
                    _style.Font.Size = New FontUnit("XSmall")
                    _style.BackColor = Color.LightGreen
                    _style.ForeColor = Color.Black
                End If 

                Return _style
            End Get 
        End Property 

        ' Create a convenience field for the control. 
        Private myControl As ControlWithStyleTasks

        Public Overrides Sub Initialize(ByVal component _
          As IComponent)
            ' Create the convenience control. 
            MyBase.Initialize(component)
            myControl = CType(component, ControlWithStyleTasks)
        End Sub 

        ' The following section creates a designer action list. 
        ' Add the specific action list for this control. The  
        ' procedure here depends upon the specific order for  
        ' the list to be added, but always add the base. 
        Public Overrides ReadOnly Property ActionLists() _
          As DesignerActionListCollection

            Get 
                Dim newActionLists As New DesignerActionListCollection()
                newActionLists.AddRange(MyBase.ActionLists)
                newActionLists.Add(New MyList(Me))
                Return newActionLists
            End Get 
        End Property 

        Private _styleConfigPhysicalFile As String = "" 

        Protected Property StyleConfigurationFile() As String 
            Get 
                Return _styleConfigPhysicalFile
            End Get 
            Set(ByVal value As String)
                Dim styleConfigPhysicalFilePath As String = String.Empty
                If value.Length > 0 Then 
                    ' Access the folder and look for the Control.xml file;  
                    ' then obtain its physical path to use to set styles  
                    ' for this control and control designer.  Obtain the  
                    ' actual file and its physical path from WebApplication. 
                    Dim webApp As IWebApplication = _
                      CType(Component.Site. _
                        GetService(GetType(IWebApplication)), IWebApplication)
                    If Not (webApp Is Nothing) Then 
                        ' Look for the project items from the root. 
                        Dim dataFileProjectItem As IProjectItem = _
                          webApp.GetProjectItemFromUrl(("~/" + value))
                        If Not (dataFileProjectItem Is Nothing) Then
                            _styleConfigPhysicalFile = value
                            styleConfigPhysicalFilePath = _
                              dataFileProjectItem.PhysicalPath
                        End If 
                    End If 
                End If 

                ' Get the styles from the XML file.
                SetControlStyleFromConfiguration( _
                  styleConfigPhysicalFilePath)
            End Set 
        End Property 

        ' Open the xml document and set control properties directly. 
        Private Sub SetControlStyleFromConfiguration(ByVal _
          path As String)

            If path Is Nothing OrElse path = String.Empty Then 
                Return 
            End If 

            Dim wc As WebControl = CType(Component, WebControl)
            If wc Is Nothing Then 
                Return 
            End If 

            Dim xmlDoc As New XmlDocument()
            xmlDoc.Load(path)

            Dim stylesList As XmlNodeList = _
              xmlDoc.GetElementsByTagName("style")
            Dim i As Integer 
            For i = 0 To stylesList.Count - 1
                If stylesList(i).Attributes("name").Value = _
                  "BackColor" Then 

                    Dim pd As PropertyDescriptor = _
                      TypeDescriptor.GetProperties(wc)("BackColor")
                    If Not (pd Is Nothing) Then
                        pd.SetValue(wc, Color.FromName(stylesList(i). _
                          Attributes("value").Value))
                    End If 
                End If 
                If stylesList(i).Attributes("name").Value = _
                  "ForeColor" Then 

                    Dim pd As PropertyDescriptor = _
                      TypeDescriptor.GetProperties(wc)("ForeColor")
                    If Not (pd Is Nothing) Then
                        pd.SetValue(wc, Color.FromName(stylesList(i). _
                          Attributes("value").Value))
                    End If 
                End If 
            Next i
        End Sub 

        ' Create the action list for this control. 
        Private Class MyList
            Inherits DesignerActionList
            Private _parent As ControlWithStyleTasksDesigner

            Public Sub New(ByVal parent As ControlWithStyleTasksDesigner)
                MyBase.New(parent.Component)
                _parent = parent
            End Sub

            <TypeConverter(GetType(FileListTypeConverter))> _
            Public Property ConfigureControlStyle() As String 
                Get 
                    Return _parent.StyleConfigurationFile
                End Get 
                Set(ByVal value As String)
                    _parent.StyleConfigurationFile = value
                End Set 
            End Property 

            ' Provide the list of sorted action items for the host. 
            ' Note that you can define the items through constructors  
            ' or through metadata on the method or property items. 
            Public Overrides Function GetSortedActionItems() _
              As DesignerActionItemCollection

                Dim items As New DesignerActionItemCollection()

                items.Add(New DesignerActionTextItem("Configuration", "Select"))
                items.Add(New DesignerActionPropertyItem("ConfigureControlStyle", _
                                                 "Configure XML", _
                                                 "Select", _
                                                 String.Empty))
                Return items
            End Function 

            ' The type converter needs to be generated with a standard  
            ' collection of items from the project. 
            Private Class FileListTypeConverter
                Inherits TypeConverter

                Public Overrides Function GetStandardValues(ByVal context _
                  As ITypeDescriptorContext) As StandardValuesCollection

                    Dim myList As MyList = CType(context.Instance, MyList)
                    Dim webApp As IWebApplication = CType(myList._parent. _
                      Component.Site.GetService(GetType(IWebApplication)), _
                                                IWebApplication)

                    Dim xmlFiles As New ArrayList()
                    Dim rootItem As IFolderProjectItem = _
                      CType(webApp.RootProjectItem, IFolderProjectItem)
                    Dim item As IProjectItem
                    For Each item In rootItem.Children
                        If String.Equals( _
                          Path.GetExtension(item.Name), ".xml", _
                          StringComparison.CurrentCultureIgnoreCase) Then

                            xmlFiles.Add(item.Name)
                        End If 
                    Next item

                    Return New StandardValuesCollection(xmlFiles)
                End Function 

                Public Overrides Function GetStandardValuesExclusive( _
                  ByVal context As ITypeDescriptorContext) As Boolean 

                    Return False 
                End Function 

                Public Overrides Function GetStandardValuesSupported( _
                  ByVal context As ITypeDescriptorContext) As Boolean 

                    Return True 
                End Function 
            End Class 
        End Class 
    End Class 

    ' This control designer is used to obtain the  
    ' configuration setting for the title. 
    Public Class ControlWithConfigurationSettingDesigner
        Inherits PanelContainerDesigner

        Public Sub New()
        End Sub 

        Private _style As Style = Nothing 

        Public Overrides ReadOnly Property FrameCaption() _
          As String 

            Get 
                Dim title As String = String.Empty
                Dim webApp As IWebApplication
                webApp = CType(Component.Site.GetService( _
                                  GetType(IWebApplication)), IWebApplication)
                If Not (webApp Is Nothing) Then 
                    ' Get the Configuration API. 
                    Dim config As System.Configuration.Configuration
                    config = webApp.OpenWebConfiguration(True)

                    If Not (config Is Nothing) Then 
                        Dim settingsSection As AppSettingsSection
                        settingsSection = config.AppSettings

                        If Not (settingsSection Is Nothing) Then
                            title = " .... " & _
                                settingsSection.Settings("ContainerControlTitle").ToString() _
                                & " ..... " 
                        End If 
                    End If 
                End If 
                Return title
            End Get 
        End Property 

        Public Overrides ReadOnly Property FrameStyle() As Style
            Get 
                If _style Is Nothing Then
                    _style = New Style()
                    _style.Font.Name = "Verdana"
                    _style.Font.Size = New FontUnit("XSmall")
                    _style.BackColor = Color.LightGreen
                    _style.ForeColor = Color.Black
                End If 

                Return _style
            End Get 
        End Property 
    End Class 

    ' This control designer reads from the project file.
    <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
    Public Class ControlWithButtonTasksDesigner
        Inherits PanelContainerDesigner

        Public Sub New()
        End Sub 
        Private _style As Style = Nothing 

        ' Add the caption by default. Note that the caption  
        ' will only appear if the Web server control  
        ' allows child controls rather than properties.  
        Public Overrides ReadOnly Property FrameCaption() _
          As String 

            Get 
                Return "Container adding controls to the document." 
            End Get 
        End Property 

        Public Overrides ReadOnly Property FrameStyle() _
          As Style

            Get 
                If _style Is Nothing Then
                    _style = New Style()
                    _style.Font.Name = "Verdana"
                    _style.Font.Size = New FontUnit("XSmall")
                    _style.BackColor = Color.LightGreen
                    _style.ForeColor = Color.Black
                End If 

                Return _style
            End Get 
        End Property 

        ' The following section creates a designer action list. 
        ' Add the specific action list for this control. The  
        ' procedure here depends upon the specific order for the  
        ' list to be added, but always add the base. 
        Public Overrides ReadOnly Property ActionLists() _
          As DesignerActionListCollection

            Get 
                Dim newActionLists As New DesignerActionListCollection()
                newActionLists.AddRange(MyBase.ActionLists)
                newActionLists.Add(New ControlWithButtonTasksList(Me))
                Return newActionLists
            End Get 
        End Property 


        Public Sub AddButton()
            ' Add a standard button. 
            Dim b As New Button()
            b.Text = "New Button"
            RootDesigner.AddControlToDocument(b, Nothing, ControlLocation.Last)
        End Sub 'AddButton

        Public Sub AddNewButton()
            ' Add your custom button. 
            Dim b As New NewButton()
            b.Text = "New custom button" 

            ' For buttons defined in a different assembly, add the   
            ' register directive for the referenced assembly.  
            ' By default, this goes to the document, unless  
            ' already defined in the document or in configuration. 
            Dim wfrm As WebFormsReferenceManager = RootDesigner.ReferenceManager
            wfrm.RegisterTagPrefix(b.GetType())

            RootDesigner.AddControlToDocument(b, Nothing, ControlLocation.First)
        End Sub 


        ' Create the action list for this control. 
        Private Class ControlWithButtonTasksList
            Inherits DesignerActionList
            Private _parent As ControlWithButtonTasksDesigner

            Public Sub New(ByVal parent As ControlWithButtonTasksDesigner)
                MyBase.New(parent.Component)
                _parent = parent
            End Sub 

            Public Sub AddButton()
                _parent.AddButton()
            End Sub 

            Public Sub AddNewButton()
                _parent.AddNewButton()
            End Sub 

            ' Provide the list of sorted action items for the host. 
            Public Overrides Function GetSortedActionItems() _
              As DesignerActionItemCollection

                Dim items As New DesignerActionItemCollection()

                items.Add(New DesignerActionTextItem("Add Control", "Add"))
                items.Add(New DesignerActionMethodItem(Me, _
                                               "AddButton", _
                                               "Add a Button", _
                                               "Add", _
                                               String.Empty, _
                                               False))
                items.Add(New DesignerActionMethodItem(Me, _
                                               "AddNewButton", _
                                               "Add a custom Button", _
                                               "Add", _
                                               String.Empty, _
                                               False))

                Return items
            End Function 
        End Class 
    End Class 

End Namespace
namespace Samples.AspNet.CS.Controls
{
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Drawing;
    using System.IO;
    using System.Text;
    using System.Web.UI;
    using System.Web.UI.Design;
    using System.Web.UI.Design.WebControls;
    using System.Web.UI.WebControls;
    using System.Reflection;
    using System.Xml;
    using System.Configuration;

    // This region-based control renders the content of an XML file.
    [
      Designer(typeof(ControlWithStyleTasksDesigner)),
      ToolboxData("<{0}:ControlWithStyleTasks runat=\"server\" "
                  + "width=\"100%\"></{0}:ControlWithStyleTasks>")
    ]
    public class ControlWithStyleTasks : Panel { }

    [
      Designer(typeof(ControlWithConfigurationSettingDesigner)),
      ToolboxData("<{0}:ControlWithConfigurationSetting runat=\"server\" "
                  + "width=\"100%\"></{0}:ControlWithConfigurationSetting>")
    ]
    public class ControlWithConfigurationSetting : Panel { }

    [
      Designer(typeof(ControlWithButtonTasksDesigner)),
      ToolboxData("<{0}:ControlWithButtonTasks runat=\"server\" "
                  + "width=\"100%\"></{0}:ControlWithButtonTasks>")
    ]
    public class ControlWithButtonTasks : Panel { }


    // Declare a custom button to add dynamically at design time. 
    public class NewButton : Button
    {
        public NewButton() { Text = "NewButton"; }
    }


    // This control designer is used to read xml files from the project.
    [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
    public class ControlWithStyleTasksDesigner : PanelContainerDesigner
    {
        private Style _style = null;

        public override string FrameCaption
        {
            get
            {
                return "Container getting styles from the project item.";
            }
        }

        public override Style FrameStyle
        {
            get
            {
                if (_style == null)
                {
                    _style = new Style();
                    _style.Font.Name = "Verdana";
                    _style.Font.Size = new FontUnit("XSmall");
                    _style.BackColor = Color.LightGreen;
                    _style.ForeColor = Color.Black;
                }

                return _style;
            }
        }

        // Create a convenience field for the control. 
        private ControlWithStyleTasks myControl;
        public override void Initialize(IComponent component)
        {
            // Create the convenience control. 
            base.Initialize(component);
            myControl = (ControlWithStyleTasks)component;
        }

        // The following section creates a designer action list. 
        // Add the specific action list for this control. The  
        // procedure here depends upon the specific order for  
        // the list to be added, but always add the base. 
        public override DesignerActionListCollection ActionLists
        {
            get
            {
                DesignerActionListCollection actionLists =
                  new DesignerActionListCollection();
                actionLists.AddRange(base.ActionLists);
                actionLists.Add(new MyList(this));
                return actionLists;
            }
        }

        private string _styleConfigPhysicalFile = "";
        protected string StyleConfigurationFile
        {
            get { return _styleConfigPhysicalFile; }
            set
            {
                string styleConfigPhysicalFilePath = String.Empty;
                if (value.Length > 0)
                {
                    // Access the folder and look for the Control.xml file;  
                    // then obtain its physical path to use to set styles  
                    // for this control and control designer.  Obtain the  
                    // actual file and its physical path from WebApplication.
                    IWebApplication webApp =
                      (IWebApplication)Component.Site.GetService(
                        typeof(IWebApplication));
                    if (webApp != null)
                    {
                        // Look for the project items from the root.
                        IProjectItem dataFileProjectItem =
                          webApp.GetProjectItemFromUrl("~/" + value);
                        if (dataFileProjectItem != null)
                        {
                            _styleConfigPhysicalFile = value;
                            styleConfigPhysicalFilePath =
                              dataFileProjectItem.PhysicalPath;
                        }
                    }
                }

                // Get the styles from the XML file.
                SetControlStyleFromConfiguration(styleConfigPhysicalFilePath);
            }
        }

        // Open the XML document and set control properties directly. 
        private void SetControlStyleFromConfiguration(string path)
        {
            if (path == null || path == String.Empty)
                return;

            WebControl wc = (WebControl)Component;
            if (wc == null)
                return;

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(path);

            XmlNodeList stylesList = xmlDoc.GetElementsByTagName("style");
            for (int i = 0; i < stylesList.Count; i++)
            {
                if (stylesList[i].Attributes["name"].Value == "BackColor")
                {
                    PropertyDescriptor pd =
                      TypeDescriptor.GetProperties(wc)["BackColor"];
                    if (pd != null)
                        pd.SetValue(wc,
                          Color.FromName(stylesList[i].Attributes["value"].Value));
                }
                if (stylesList[i].Attributes["name"].Value == "ForeColor")
                {
                    PropertyDescriptor pd =
                      TypeDescriptor.GetProperties(wc)["ForeColor"];
                    if (pd != null)
                        pd.SetValue(wc,
                          Color.FromName(stylesList[i].Attributes["value"].Value));
                }
            }
        }

        // Create the action list for this control. 
        private class MyList : DesignerActionList
        {
            private ControlWithStyleTasksDesigner _parent;

            public MyList(ControlWithStyleTasksDesigner parent)
                : base(parent.Component)
            {
                _parent = parent;
            }

            [
              TypeConverter(typeof(FileListTypeConverter))
            ]
            public string ConfigureControlStyle
            {
                get { return _parent.StyleConfigurationFile; }
                set
                {
                    _parent.StyleConfigurationFile = value;
                }
            }

            // Provide the list of sorted action items for the host. 
            // Note that you can define the items through constructors  
            // or through metadata on the method or property items. 
            public override DesignerActionItemCollection GetSortedActionItems()
            {
                DesignerActionItemCollection items = new DesignerActionItemCollection();

                items.Add(new DesignerActionTextItem("Configuration",
                                                      "Select"));
                items.Add(new DesignerActionPropertyItem("ConfigureControlStyle",
                                               "Configure XML",
                                               "Select",
                                               String.Empty));
                return items;
            }

            // The type converter needs to be generated with a standard  
            // collection of items from the project. 
            private class FileListTypeConverter : TypeConverter
            {
                public override StandardValuesCollection
                  GetStandardValues(ITypeDescriptorContext context)
                {
                    MyList myList = (MyList)context.Instance;
                    IWebApplication webApp =
                      (IWebApplication)myList._parent.Component.Site.GetService(
                        typeof(IWebApplication));

                    ArrayList xmlFiles = new ArrayList();
                    IFolderProjectItem rootItem =
                      (IFolderProjectItem)webApp.RootProjectItem;
                    foreach (IProjectItem item in rootItem.Children)
                    {
                        if (String.Equals(Path.GetExtension(item.Name),
                                          ".xml",
                                          StringComparison.CurrentCultureIgnoreCase))
                        {
                            xmlFiles.Add(item.Name);
                        }
                    }

                    return new StandardValuesCollection(xmlFiles);
                }

                public override bool GetStandardValuesExclusive(
                  ITypeDescriptorContext context)
                {
                    return false;
                }
                public override bool GetStandardValuesSupported(
                  ITypeDescriptorContext context)
                {
                    return true;
                }
            }
        }

    }

    // This control designer is used to obtain the  
    // configuration setting for the title. 
    public class ControlWithConfigurationSettingDesigner : PanelContainerDesigner
    {
        public ControlWithConfigurationSettingDesigner() { }

        private Style _style = null;

        public override string FrameCaption
        {
            get
            {
                string title = String.Empty;
                IWebApplication webApp =
                  (IWebApplication)Component.Site.GetService(
                    typeof(IWebApplication));
                if (webApp != null)
                {
                    // Get the Configuration API.
                    Configuration config = webApp.OpenWebConfiguration(true);
                    if (config != null)
                    {
                        AppSettingsSection settingsSection = config.AppSettings;
                        if (settingsSection != null)
                        {
                            title =
                              " .... "
                              + settingsSection.Settings["ContainerControlTitle"]
                              + " ..... ";
                        }
                    }
                }
                return title;
            }
        }

        public override Style FrameStyle
        {
            get
            {
                if (_style == null)
                {
                    _style = new Style();
                    _style.Font.Name = "Verdana";
                    _style.Font.Size = new FontUnit("XSmall");
                    _style.BackColor = Color.LightGreen;
                    _style.ForeColor = Color.Black;
                }

                return _style;
            }
        }
    }

    // This control designer reads from the project file.
    [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]
    public class ControlWithButtonTasksDesigner : PanelContainerDesigner
    {
        public ControlWithButtonTasksDesigner() { }

        private Style _style = null;

        // Add the caption by default. Note that the caption  
        // will only appear if the Web server control  
        // allows child controls rather than properties.  
        public override string FrameCaption
        {
            get { return "Container adding controls to the document."; }
        }

        public override Style FrameStyle
        {
            get
            {
                if (_style == null)
                {
                    _style = new Style();
                    _style.Font.Name = "Verdana";
                    _style.Font.Size = new FontUnit("XSmall");
                    _style.BackColor = Color.LightGreen;
                    _style.ForeColor = Color.Black;
                }

                return _style;
            }
        }

        // The following section creates a designer action list. 
        // Add the specific action list for this control. The  
        // procedure here depends upon the specific order for the  
        // list to be added, but always add the base. 
        public override DesignerActionListCollection ActionLists
        {
            get
            {
                DesignerActionListCollection actionLists =
                  new DesignerActionListCollection();
                actionLists.AddRange(base.ActionLists);
                actionLists.Add(new MyList3(this));
                return actionLists;
            }
        }

        public void AddButton()
        {
            // Add a standard button.
            Button b = new Button();
            b.Text = "New standard button";
            RootDesigner.AddControlToDocument(b, null, ControlLocation.First);
        }


        public void AddNewButton()
        {
            // Add your custom button.
            NewButton b = new NewButton();
            b.Text = "New custom button";

            // For buttons defined in a different assembly, add the   
            // register directive for the referenced assembly.  
            // assembly. By default, this goes to the document, unless  
            // already defined in the document or in configuration.
            WebFormsReferenceManager wfrm =
              RootDesigner.ReferenceManager;
            wfrm.RegisterTagPrefix(b.GetType());

            RootDesigner.AddControlToDocument(b, null, ControlLocation.Last);
        }


        // Create the action list for this control. 
        private class MyList3 : DesignerActionList
        {
            private ControlWithButtonTasksDesigner _parent;
            public MyList3(ControlWithButtonTasksDesigner parent)
                : base(parent.Component)
            {
                _parent = parent;
            }

            public void AddButton()
            {
                _parent.AddButton();
            }
            public void AddNewButton()
            {
                _parent.AddNewButton();
            }

            // Provide the list of sorted action items for the host. 
            public override DesignerActionItemCollection GetSortedActionItems()
            {
                DesignerActionItemCollection items = new DesignerActionItemCollection();

                items.Add(new DesignerActionTextItem("Add Control", "Add"));
                items.Add(new DesignerActionMethodItem(this,
                                               "AddButton",
                                               "Add a Button",
                                               "Add",
                                               String.Empty,
                                               false));
                items.Add(new DesignerActionMethodItem(this,
                                               "AddNewButton",
                                               "Add a custom Button",
                                               "Add",
                                               String.Empty,
                                               false));
                return items;
            }
        }
    }
}

See Also

Tasks

Walkthrough: Creating a Basic Control Designer for a Web Server Control

Concepts

ASP.NET Control Designers Overview

Sample Control Designer with Action Lists and Services