Walkthrough: Customizing ToolboxItem Configuration Dynamically

This walkthrough shows how a managed VSPackage can supply dynamic configuration support for the ToolboxItem objects.

Note

The simplest way to add custom controls to the Toolbox is to use the Toolbox Control templates that come with the Visual Studio 10 SDK. This topic relates to advanced Toolbox development.

For more information on creating toolbox controls by using the templates, see How to: Create a Toolbox Control That Uses Windows Forms and How to: Create a Toolbox Control That Uses WPF.

This walkthrough guides you through the following steps:

  1. Add and correctly register all Toolbox controls in the VSPackage objects by using the ToolboxItemAttribute and ToolboxBitmapAttribute classes.

  2. Create the following two controls and add icons for each of them to the Toolbox:

    • One control that declares an associated default ToolboxItem.

    • One control that declares an associated custom Toolbox item that is derived from the ToolboxItem class.

  3. Write an implementation of IConfigureToolboxItem, and register it by doing the following things:

    1. Defining a filter class that derives from the IConfigureToolboxItem class and specifies the ToolboxItem instances that this implementation will act on.

    2. Applying a ProvideToolboxItemConfigurationAttribute, which references the filter class, to the class that implements the Package class for the VSPackage.

  4. Register the VSPackage as a provider of ToolboxItem objects by applying the ProvideToolboxItemsAttribute to the class that implements the Package class for the VSPackage.

  5. At package load time, use reflection to generate a list of all ToolboxItem objects that the VSPackage provides.

  6. Create a handler for the ToolboxInitialized and ToolboxUpgraded events. Doing this guarantees that the VSPackage's ToolboxItem objects are correctly loaded.

  7. Implement a command on the VSPackage to force re-initialization of the Toolbox.

Prerequisites

To complete this walkthrough, you must install the Visual Studio 2012 SDK.

Note

For more information about the Visual Studio SDK, see Extending Visual Studio Overview. To find out how to download the Visual Studio SDK, see Visual Studio Extensibility Developer Center on the MSDN Web site.

Locations for the Visual Studio Package Project Template

The Visual Studio Package project template can be found in three different locations in the New Project dialog:

  1. Under Visual Basic Extensibility. The default language of the project is Visual Basic.

  2. Under C# Extensibility. The default language of the project is C#.

  3. Under Other Project Types Extensibility. The default language of the project is C++.

Creating a Managed VSPackage

Complete the following procedures to create a managed VSPackage.

To create a managed VSPackage to provide toolbox items

  1. Create a VSPackage named ItemConfiguration. For more information, see Walkthrough: Creating a Menu Command By Using the Visual Studio Package Template.

  2. In the Visual Studio Package template, add a menu command.

    Name the command Initialize ItemConfigurationVB for Visual Basic or Initialize ItemConfigurationCS for Visual C#.

  3. For Visual Basic, add the following namespaces to the imported namespaces list in the generated project:

    • Company.ItemConfiguration

    • System

    • System.ComponentModel

    • System.Drawing

    • System.Windows.Forms

  4. Add a reference to the System.Drawing.Design .NET Framework component.

If you follow this walkthrough for more than one language, you must update the project to disambiguate the generated assemblies.

To disambiguate Visual Basic and Visual C# VSPackages

  1. For Visual Basic:

    1. Open the project properties, and select the Application tab.

      Change the assembly name to ItemConfigurationVB, and change the default namespace to Company.ItemConfigurationVB.

    2. Select the References tab.

      Update the imported namespaces list.

      Remove Company.ItemConfiguration.

      Add Company.ItemConfigurationVB.

  2. For Visual C#:

    1. Open the project properties, and select the Application tab.

      Change the assembly name to ItemConfigurationCS, and change the default namespace to Company.ItemConfigurationCS.

    2. Open the ItemConfigurationPackage class in the code editor.

      To use the refactoring tools to rename the existing namespace, right-click the existing namespace name, ItemConfiguration, point to Refactor, and then click Rename. Change the name to ItemConfigurationCS.

  3. Save all changes.

To test the generated code

  1. Compile and start the VSPackage in the Visual Studio experimental hive.

  2. On the Tools menu, click Initialize Item Configuration VB or Initialize Item Configuration CS.

    Doing this opens a message box that contains text that indicates that the package's menu item handler was called.

  3. Close the experimental version of Visual Studio.

Creating Toolbox Controls

In this section, you create and register a user control, Control1, that declares an associated default Toolbox item. You also create and register a second user control, Control2, and an associated custom Toolbox item, Control2_ToolboxItem, that is derived from the ToolboxItem class. For more information about how to author Windows Forms controls and ToolboxItem classes, see Developing Windows Forms Controls at Design Time.

To create default and custom toolbox items

  1. Use the instructions in Walkthrough: Autoloading Toolbox Items to create a default Toolbox item and a custom Toolbox item, as follows.

    1. Complete the procedure, "To create a Toolbox control that will be used with a default ToolboxItem." Update the DescriptionAttribute to reference this project.

      The resulting code for the Control1 class should resemble the following code.

      ' Set the display name and custom bitmap to use for this item. 
      ' The build action for the bitmap must be "Embedded Resource".
      <DisplayName("ToolboxMember 1 VB")> _
      <Description("Custom toolbox item from package ItemConfiguration.")> _
      <ToolboxItem(True)> _
      <ToolboxBitmap(GetType(Control1), "Control1.bmp")> _
      Public Class Control1
      
          Public Sub New()
      
              InitializeComponent()
      
              Button1.Text = Me.Name + " Button" 
          End Sub 
      
          Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
              Handles Button1.Click
      
              MessageBox.Show("Hello world from " & Me.ToString())
          End Sub 
      End Class
      
      using System;
      using System.ComponentModel;
      using System.Drawing;
      using System.Windows.Forms;
      
      namespace Company.ItemConfigurationCS
      {
          // Set the display name and custom bitmap to use for this item. 
          // The build action for the bitmap must be "Embedded Resource".
          [DisplayName("ToolboxMember 1 CS")]
          [Description("Custom toolbox item from package ItemConfiguration.")]
          [ToolboxItem(true)]
          [ToolboxBitmap(typeof(Control1), "Control1.bmp")]
          public partial class Control1 : UserControl
          {
              public Control1()
              {
                  InitializeComponent();
      
                  button1.Text = this.Name + " Button";
              }
      
              private void button1_Click(object sender, EventArgs e)
              {
                  MessageBox.Show("Hello world from " + this.ToString());
              }
          }
      }
      
    2. Complete the procedure, "To create a Toolbox control for using a custom ToolboxItem-derived class." Update the DescriptionAttribute to reference this project.

      The resulting code for the Control2 and Control2_ToolboxItem classes should resemble the following code.

      Imports System.Drawing.Design
      Imports System.Globalization
      
      ' Set the display name and custom bitmap to use for Me item. 
      ' The build action for the bitmap must be "Embedded Resource". 
      ' Also declare a custom toolbox item implementation.
      <DisplayName("ToolboxMember 2 VB")> _
      <Description("Custom toolbox item from package ItemConfiguration.")> _
      <ToolboxItem(GetType(Control2_ToolboxItem))> _
      <ToolboxBitmap(GetType(Control2), "Control2.bmp")> _
      Public Class Control2
      
          Public Sub New()
              InitializeComponent()
      
              Button1.Text = Me.Name + " Button" 
          End Sub 
      
          Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
              Handles Button1.Click
      
              MessageBox.Show("Hello world from " & Me.ToString())
          End Sub 
      End Class
      
      <Serializable()> _
      Friend Class Control2_ToolboxItem
          Inherits ToolboxItem
      
          Public Sub New(ByVal toolType As Type)
              MyBase.New(toolType)
          End Sub 
      
          Public Overrides Sub Initialize(ByVal toolType As Type)
      
              If Not toolType.Equals(GetType(Control2)) Then 
                  Throw New ArgumentException( _
                      String.Format(CultureInfo.CurrentCulture, _
                          "The {0} constructor argument must be of type {1}.", _
                          Me.GetType().FullName, GetType(Control2).FullName))
              End If 
      
              MyBase.Initialize(toolType)
          End Sub 
      End Class
      
      using System;
      using System.ComponentModel;
      using System.Drawing;
      using System.Windows.Forms;
      
      using System.Drawing.Design;
      using System.Globalization;
      
      namespace Company.ItemConfigurationCS
      {
          // Set the display name and custom bitmap to use for this item. 
          // The build action for the bitmap must be "Embedded Resource".
          // Also declare a custom toolbox item implementation.
          [DisplayName("ToolboxMember 2 CS")]
          [Description("Custom toolbox item from package ItemConfigurationPackage.")]
          [ToolboxItem(typeof(Control2_ToolboxItem))]
          [ToolboxBitmap(typeof(Control2), "Control2.bmp")]
          public partial class Control2 : UserControl
          {
              public Control2()
              {
                  InitializeComponent();
      
                  button1.Text = this.Name + " Button";
              }
      
              private void button1_Click(object sender, EventArgs e)
              {
                  MessageBox.Show("Hello world from " + this.ToString());
              }
          }
      
          [Serializable()]
          internal class Control2_ToolboxItem : ToolboxItem
          {
              public Control2_ToolboxItem(Type toolType)
                  : base(toolType) { }
      
              public override void Initialize(Type toolType)
              {
                  if (!toolType.Equals(typeof(Control2)))
                  {
                      throw new ArgumentException(
                          string.Format(CultureInfo.CurrentCulture,
                              "The {0} constructor argument must be of type {1}.",
                              this.GetType().FullName, typeof(Control2).FullName));
                  }
      
                  base.Initialize(toolType);
              }
          }
      }
      
  2. Save the files.

Embedding Bitmap Icons

The ToolboxBitmapAttribute attribute that is applied to each control specifies which icon to associate with that control. Create the bitmaps for both controls, and name them as follows:

  • Control1.bmp, for the Control1 class.

  • Control2.bmp, for the Control2 class.

To embed a bitmap icon for a Toolbox item

  1. Add a new bitmap to the project, as follows:

    1. In Solution Explorer, right-click the VSPackage project, point to Add, and then click New Item.

    2. In the Add New Item dialog box, select Bitmap File, and enter the name of the bitmap.

  2. Use the bitmap editor to create a 16∝16 icon, as follows.

    1. On the View menu, click Properties Window.

    2. In the Properties window, set Height and Width to 16.

    3. Use the editor to create the icon image.

  3. In Solution Explorer, right-click the bitmap item, and then click Properties.

  4. Set the Build Action property to Embedded Resource.

  5. Save all open files.

Adding a Dynamic Toolbox Configuration Provider

In this section, you create and register a class that implements the IConfigureToolboxItem interface. This class is instantiated and used by the Visual Studio integrated development environment (IDE) to configure Toolbox controls.

Note

Because the Visual Studio environment instantiates an instance of the implementation of IConfigureToolboxItem, do not implement the IConfigureToolboxItem interface on the class that implements Package for a VSPackage.

To create and register a toolbox control configuration object

  1. In Solution Explorer, add a class to the ItemConfiguration project, and name it ToolboxConfig.

  2. Add the following namespace statements to the file.

    Imports Microsoft.VisualStudio.Shell
    Imports System.Collections
    Imports System.ComponentModel
    Imports System.Drawing.Design
    Imports System.Reflection
    Imports System.Runtime.InteropServices
    Imports System.Security.Permissions
    
    using Microsoft.VisualStudio.Shell;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    
  3. Ensure that the ToolboxConfig class is public and implements the IConfigureToolboxItem interface.

  4. Apply a GuidAttribute and a ProvideAssemblyFilterAttribute to the ToolboxConfig class.

    • For Visual Basic, use an assembly name of "ItemConfigurationVB, Version=*, Culture=*, PublicKeyToken=*".

    • For Visual C#, use an assembly name of "ItemConfigurationCS, Version=*, Culture=*, PublicKeyToken=*".

    Doing this restricts the ToolboxConfig class to working on ToolboxItem objects that are provided by the assembly that contains the current VSPackage.

    <ProvideAssemblyFilter("ItemConfigurationVB, Version=*, Culture=*, PublicKeyToken=*")> _
    <Guid("4DDC7895-442A-45e7-82E7-4E85F243C321")> _
    Public Class ToolboxConfig
        Implements IConfigureToolboxItem
    
    [ProvideAssemblyFilter("ItemConfigurationCS, Version=*, Culture=*, PublicKeyToken=*")]
    [Guid("E6832593-BF07-4de1-AA0F-7F9B94887DB8")]
    public class ToolboxConfig : IConfigureToolboxItem
    

    You can generate a GUID by clicking Create GUID on the Tools menu. Select the format with square braces, click Copy, and then paste the GUID in your code. change the keyword GUID to Guid.

  5. Implement the ConfigureToolboxItem method of the IConfigureToolboxItem interface so that the method only acts on the two ToolboxItem classes, Control1 and Control2.

    The implementation of ConfigureToolboxItem applies instances of ToolboxItemFilterAttribute to the two ToolboxItem objects so that:

    • The ToolboxItem that is implemented by Control1 is only available in the Toolbox for designers that handle UserControl objects.

    • The ToolboxItem that is implemented by Control2 is not available in the Toolbox for designers that handle UserControl objects.

    <PrincipalPermission(SecurityAction.Demand)> Public Sub _
        ConfigureToolboxItem(ByVal item As ToolboxItem) _
        Implements IConfigureToolboxItem.ConfigureToolboxItem
    
        If item Is Nothing Then Return 
    
        ' Create a filter for the Toolbox. 
        Dim newFilter As ToolboxItemFilterAttribute
        If GetType(Control1).ToString() = item.TypeName Then 
    
            ' For Control1, only show it when editing a UserControl.
            newFilter = New ToolboxItemFilterAttribute( _
                "System.Windows.Forms.UserControl", _
                ToolboxItemFilterType.Require)
    
        ElseIf GetType(Control2).ToString() = item.TypeName Then 
    
            ' For Control2, only show it when not editing a UserControl.
            newFilter = New ToolboxItemFilterAttribute( _
                "System.Windows.Forms.UserControl", _
                ToolboxItemFilterType.Prevent)
    
        Else 
    
            ' Don't apply a filter to other classes. 
            Return 
    
        End If
    
        item.Filter = CType(New ToolboxItemFilterAttribute() {newFilter}, ICollection)
    End Sub
    
    [PrincipalPermission(SecurityAction.Demand)]
    public void ConfigureToolboxItem(ToolboxItem item)
    {
        if (null == item) return;
    
        // Create a filter for the Toolbox.
        ToolboxItemFilterAttribute newFilter;
        if (typeof(Control1).ToString() == item.TypeName)
        {
            // For Control1, only show it when editing a UserControl.
            newFilter = new ToolboxItemFilterAttribute(
                "System.Windows.Forms.UserControl",
                ToolboxItemFilterType.Require);
        }
        else if (typeof(Control2).ToString() == item.TypeName)
        {
            // For Control2, only show it when not editing a UserControl.
            newFilter = new ToolboxItemFilterAttribute(
                "System.Windows.Forms.UserControl",
                ToolboxItemFilterType.Prevent);
        }
        else
        {
            // Don't apply a filter to other classes. 
            return;
        }
    
        item.Filter = (ICollection)(new ToolboxItemFilterAttribute[] { newFilter });
    }
    

Modifying the VSPackage Implementation

The default implementation of the VSPackage that is provided by the Visual Studio Package template must be modified to do the following things:

  • Register as a Toolbox item provider.

  • Register the class that provides the dynamic Toolbox control configuration for the VSPackage.

  • Use the ToolboxService to load all the ToolboxItem objects that are provided by the VSPackage assembly.

  • Handle ToolboxInitialized and ToolboxUpgraded events.

To modify the Package implementation for a Toolbox item provider on the VSPackage

  1. Open the ItemConfigurationPackage class in the code editor.

  2. Modify the declaration of the ItemConfigurationPackage class, which is the implementation of the Package class in the solution.

    1. Add the following namespace statements to the file.

      Imports System.Collections
      Imports System.ComponentModel
      Imports System.Drawing.Design
      Imports System.Reflection
      
      using System.Collections;
      using System.ComponentModel;
      using System.Drawing.Design;
      using System.Reflection;
      
    2. To register the VSPackage as providing Toolbox items, apply a ProvideToolboxItemsAttribute to the package. To register the ToolboxConfig class as providing a Toolbox control dynamic configuration, apply a ProvideToolboxItemConfigurationAttribute to the package.

      ' ...
      <PackageRegistration(UseManagedResourcesOnly:=True), _
          DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\9.0"), _
          InstalledProductRegistration(False, "#110", "#112", "1.0", IconResourceID:=400), _
          ProvideLoadKey("Standard", "1.0", "Package Name", "Company", 1), _
          ProvideMenuResource(1000, 1), _
          Guid(GuidList.guidItemConfigurationPkgString)> _
          <ProvideToolboxItems(1)> _
          <ProvideToolboxItemConfiguration(GetType(ToolboxConfig))> _
          Public NotInheritable Class ItemConfigurationPackage
          Inherits Package
      
      // ...
      [PackageRegistration(UseManagedResourcesOnly = true)]
      // ...
      [DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\9.0")]
      // ...
      [InstalledProductRegistration(false, "#110", "#112", "1.0", IconResourceID = 400)]
      // ...
      [ProvideLoadKey("Standard", "1.0", "Package Name", "Company", 1)]
      // ...
      [ProvideMenuResource(1000, 1)]
      [Guid(GuidList.guidItemConfigurationPkgString)]
      [ProvideToolboxItems(1)]
      [ProvideToolboxItemConfiguration(typeof(ToolboxConfig))]
      public sealed class ItemConfigurationPackage : Package
      

      Note

      The only argument of ProvideToolboxItemsAttribute is the version of ToolboxItem that is provided by the VSPackage. By changing this value, you force the IDE to load the VSPackage even if it has an earlier cached version of ToolboxItem.

    3. Create two new private fields in the ItemConfiguration class, as follows:

      An ArrayList member, named ToolboxItemList, to hold a list of the ToolboxItem objects that the ItemConfiguration class manages.

      A String, named CategoryTab, that contains the Toolbox tab that is used to hold the ToolboxItem objects that the ItemConfiguration class manages.

      Private ToolboxItemList As ArrayList
      Private Shared ReadOnly CategoryTab As String = _
          "ItemConfiguration Walkthrough VB"
      
      private ArrayList ToolboxItemList;
      private static readonly string CategoryTab =
          "ItemConfiguration Walkthrough CS";
      

    The result of this modification resembles the following code:

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Diagnostics
    Imports System.Globalization
    Imports System.Runtime.InteropServices
    Imports System.ComponentModel.Design
    Imports Microsoft.Win32
    Imports Microsoft.VisualStudio.Shell.Interop
    Imports Microsoft.VisualStudio.OLE.Interop
    Imports Microsoft.VisualStudio.Shell
    
    Imports System.Collections
    Imports System.ComponentModel
    Imports System.Drawing.Design
    Imports System.Reflection
    
    ' ...
    <PackageRegistration(UseManagedResourcesOnly:=True), _
        DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\9.0"), _
        InstalledProductRegistration(False, "#110", "#112", "1.0", IconResourceID:=400), _
        ProvideLoadKey("Standard", "1.0", "Package Name", "Company", 1), _
        ProvideMenuResource(1000, 1), _
        Guid(GuidList.guidItemConfigurationPkgString)> _
        <ProvideToolboxItems(1)> _
        <ProvideToolboxItemConfiguration(GetType(ToolboxConfig))> _
        Public NotInheritable Class ItemConfigurationPackage
        Inherits Package
    
        Private ToolboxItemList As ArrayList
        Private Shared ReadOnly CategoryTab As String = _
            "ItemConfiguration Walkthrough VB" 
    
        ' ...
    
    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Runtime.InteropServices;
    using System.ComponentModel.Design;
    using Microsoft.Win32;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio.Shell;
    
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Reflection;
    
    namespace Company.ItemConfigurationCS
    {
        // ...
        [PackageRegistration(UseManagedResourcesOnly = true)]
        // ...
        [DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\9.0")]
        // ...
        [InstalledProductRegistration(false, "#110", "#112", "1.0", IconResourceID = 400)]
        // ...
        [ProvideLoadKey("Standard", "1.0", "Package Name", "Company", 1)]
        // ...
        [ProvideMenuResource(1000, 1)]
        [Guid(GuidList.guidItemConfigurationPkgString)]
        [ProvideToolboxItems(1)]
        [ProvideToolboxItemConfiguration(typeof(ToolboxConfig))]
        public sealed class ItemConfigurationPackage : Package
        {
            private ArrayList ToolboxItemList;
            private static readonly string CategoryTab =
                "ItemConfiguration Walkthrough CS";
    
            // ...
    
  3. Define an OnRefreshToolbox method to handle the ToolboxInitialized and ToolboxUpgraded events.

    The OnRefreshToolbox method uses the list of ToolboxItem objects that is contained in the ToolboxItemList field and does the following things:

    • Removes all ToolboxItem objects from the Toolbox tab that is defined by the CategoryTab field.

    • Adds to the Toolbox tab new instances of all ToolboxItem objects that are listed in the ToolboxItemList field.

    • Sets the Toolbox tab as the active tab.

    ' Add new instances of all ToolboxItems to the toolbox item list. 
    Private Sub OnRefreshToolbox(ByVal sender As Object, ByVal e As EventArgs) _
    Handles Me.ToolboxInitialized, Me.ToolboxUpgraded
    
        Dim service As IToolboxService = _
            TryCast(GetService(GetType(IToolboxService)), IToolboxService)
        Dim toolbox As IVsToolbox = _
             TryCast(GetService(GetType(IVsToolbox)), IVsToolbox)
    
        ' Remove target tab and all items under it. 
        For Each item As ToolboxItem In service.GetToolboxItems(CategoryTab)
            service.RemoveToolboxItem(item)
        Next
        toolbox.RemoveTab(CategoryTab)
    
        ' Recreate the target tab with the items from the current list.  
        For Each item As ToolboxItem In ToolboxItemList
            service.AddToolboxItem(item, CategoryTab)
        Next
        service.SelectedCategory = CategoryTab
    
        service.Refresh()
    End Sub
    
    // Add new instances of all ToolboxItems to the toolbox item list. 
    void OnRefreshToolbox(object sender, EventArgs e)
    {
        IToolboxService service =
            GetService(typeof(IToolboxService)) as IToolboxService;
        IVsToolbox toolbox =
            GetService(typeof(IVsToolbox)) as IVsToolbox;
    
        // Remove target tab and all items under it. 
        foreach (ToolboxItem item in service.GetToolboxItems(CategoryTab))
        {
            service.RemoveToolboxItem(item);
        }
        toolbox.RemoveTab(CategoryTab);
    
        // Recreate the target tab with the items from the current list.  
        foreach (ToolboxItem item in ToolboxItemList)
        {
            service.AddToolboxItem(item, CategoryTab);
        }
        service.SelectedCategory = CategoryTab;
    
        service.Refresh();
    }
    
  4. For Visual C#, in the constructor, register the OnRefreshToolbox method as the event hander for the ToolboxInitialized and ToolboxUpgraded events.

    this.ToolboxInitialized += new EventHandler(OnRefreshToolbox);
    this.ToolboxUpgraded += new EventHandler(OnRefreshToolbox);
    
  5. Modify the Initialize method in ItemConfigurationPackage to fill the ToolboxItemList field by calling the GetToolboxItems method of the System.Drawing.Design.ToolboxService class. The Toolbox service gets all the Toolbox item classes that are defined in the currently executing assembly. The ToolboxItemList field is used by the Toolbox event handlers to load the Toolbox items.

    Add the following code at the end of the Initialize method.

    ' Use the toolbox service to get a list of all toolbox items in 
    ' this assembly.
    ToolboxItemList = New ArrayList( _
        ToolboxService.GetToolboxItems(Me.GetType().Assembly, ""))
    If ToolboxItemList Is Nothing Then 
        Throw New ApplicationException( _
            "Unable to generate a toolbox item listing for " & _
            Me.GetType().FullName)
    End If 
    
    ' Update the display name of each toolbox item in the list. 
    Dim thisAssembly As Assembly = Me.GetType().Assembly
    For Each item As ToolboxItem In ToolboxItemList
    
        Dim underlyingType As Type = thisAssembly.GetType(item.TypeName)
        Dim attribs As AttributeCollection = _
            TypeDescriptor.GetAttributes(underlyingType)
        Dim displayName As DisplayNameAttribute = _
            TryCast(attribs(GetType(DisplayNameAttribute)), DisplayNameAttribute)
    
        If displayName IsNot Nothing AndAlso Not displayName.IsDefaultAttribute() Then
            item.DisplayName = displayName.DisplayName
        End If 
    Next
    
    // Use the toolbox service to get a list of all toolbox items in 
    // this assembly.
    ToolboxItemList = new ArrayList(
        ToolboxService.GetToolboxItems(this.GetType().Assembly, ""));
    if (null == ToolboxItemList)
    {
        throw new ApplicationException(
            "Unable to generate a toolbox item listing for " +
            this.GetType().FullName);
    }
    
    // Update the display name of each toolbox item in the list.
    Assembly thisAssembly = this.GetType().Assembly;
    foreach (ToolboxItem item in ToolboxItemList)
    {
        Type underlyingType = thisAssembly.GetType(item.TypeName);
        AttributeCollection attribs =
            TypeDescriptor.GetAttributes(underlyingType);
        DisplayNameAttribute displayName =
            attribs[typeof(DisplayNameAttribute)] as DisplayNameAttribute;
        if (displayName != null && !displayName.IsDefaultAttribute())
        {
            item.DisplayName = displayName.DisplayName;
        }
    }
    

    Note

    As an exercise, one could develop a mechanism for testing the version of the VSPackage or the items, and only update if the VSPackage version has changed or if the version of the ToolboxItem has changed.

Initializing the Toolbox

To implement a command to initialize the Toolbox

  • In the ItemConfigurationPackage class, change the MenuItemCallBack method, which is the menu item's command handler.

    Replace the existing implementation of the MenuItemCallBack method by using the following code:

    Private Sub MenuItemCallback(ByVal sender As Object, ByVal e As EventArgs)
        Dim pkg As IVsPackage = TryCast(GetService(GetType(Package)), IVsPackage)
        pkg.ResetDefaults(CUInt(__VSPKGRESETFLAGS.PKGRF_TOOLBOXITEMS))
    End Sub
    
    private void MenuItemCallback(object sender, EventArgs e)
    {
        IVsPackage pkg = GetService(typeof(Package)) as IVsPackage;
        pkg.ResetDefaults((uint)__VSPKGRESETFLAGS.PKGRF_TOOLBOXITEMS);
    }
    

Building and Running the Solution

You can exercise the product of this walkthrough by using an instance of Visual Studio that is running in the experimental hive.

To exercise this walkthrough

  1. In Visual Studio, on the Build menu, click Rebuild Solution.

  2. Press F5 to start a second instance of Visual Studio in the experimental registry hive.

    For more information about how to use the experimental hive, see Experimental Instance of Visual Studio.

  3. Click the Tools menu.

    A command named Initialize ItemConfiguration VB or Initialize ItemConfiguration CS appears at the top of the menu, together with an icon that has the numeral 1.

  4. Create a new Visual C# or Visual Basic Windows Forms application.

    A Form-based designer appears.

  5. Add a user control to the project.

    A user control designer appears.

  6. Pin the Toolbox open, and switch between the two design views.

    Notice that which Toolbox item is visible and which one is hidden depends on which designer has focus.

  7. Drag the first Toolbox item onto the user control to add an instance of Control1 to the user control.

  8. Drag the second Toolbox item onto the form to add an instance of Control2 to the form.

  9. Build the Windows application.

    The user control for the application is now available in the Toolbox.

  10. Add the application's user control to the form, and then rebuild the application and run it.

    When the application runs, click each control on the form to get the associated message box.

Analysis of the Implementation

Because the assemblyFilter parameter is present in the ProvideAssemblyFilterAttribute class constructor, only ToolboxItem objects in the assembly produced in this walkthrough are acted on by the ConfigureToolboxItem method of the ToolboxConfg class.

Therefore, whenever the ItemConfiguration Walkthrough category is active on the Toolbox, the ConfigureToolboxItem method of the ToolboxConfg class is called, and ToolboxItemFilterAttribute instances are applied on the ToolboxItem objects that are implemented by Control1 and Control2.

See Also

Tasks

Advanced Toolbox Control Development

Concepts

Registering Toolbox Support Features

Other Resources

Toolbox (Visual Studio SDK)

Toolbox Walkthroughs