Known Issue: Controls and GAC, Toolbox and TCI

Introduction

The purpose of the post is to provide guidance for control authors to limit the controls added to the Toolbox and that are listed in the Choose Items Dialog.

The word "controls" in this post is defined as "any public type in a control assembly that derives from FrameworkElement or above." Both the TCI and Choose Items Dialog include all public types that derive from FrameworkElement or above.

Does This Information Apply To My Control Assemblies?

If your control assemblies are installed in the GAC and you want to limit controls visible in the Choose Items Dialog you must follow the guidance in this post.

If you use the TCI to have Visual Studio install your controls in the Toolbox and you install your control assemblies in the GAC and want to limit controls installed into the Toolbox and controls visible in the Choose Items Dialog you must follow the guidance in this post.

If you use the TCI to have Visual Studio install your controls in the Toolbox, you must have a design-time assembly to limit controls installed in the Toolbox. This applies to both WPF & Silverlight controls.

This post covers two known issues.

  • WPF only. Public types in control assemblies installed in the GAC that derive from FrameworkElement or above are now required to be decorated with the System.ComponentModel.DesignTimeVisible(false) attribute in order to keep the type from appearing in the Toolbox or the Choose Items Dialog. Not decorating the type with this attribute, could result in the type being added to the Toolbox and will result in the type being listed in the Choose Items Dialog.
  • WPF and Silverlight. Control assemblies that are installed using the TCI require a design-time assembly to limit the types added to the Toolbox and the Choose Items Dialog. Without the design-time assembly, all types deriving from FrameworkElement or above will be placed in the Toolbox and will be listed in the Choose Items Dialog.
Critical

If a control assembly is installed into the GAC and uses the TCI, you must implement both of the above steps to keep unwanted types out of the Toolbox and Choose Items.

Scenario Assemblies

The following two WPF assemblies are assumed for this post.

  • C:\Acme\Acme.Controls.dll
  • C:\Acme\Acme.Controls.Design.dll

Acme.Controls.dll

Each of the below four custom controls has a two line summary comment.  The first line of the comment describes what if any metadata is associated with the control in the design assembly.  The second line applies to the control itself.  The name of the control describes when the control will be visible.

 namespace Acme.Controls {

    /// <summary>
    /// This control has a design assembly ToolboxBrowsableAttribute false.
    /// This attribute only gets processed when this assembly is in the GAC.
    /// </summary>
    [DesignTimeVisible(false)]
    public class YouShouldNeverSeeMe : Control {
    }

    /// <summary>
    /// This control has a design assembly ToolboxBrowsableAttribute true.
    /// This control will be in the Toolbox and Choose Items.
    /// </summary>
    public class ToolboxBrowsableAttributeTrue : Control {
    }

    /// <summary>
    /// This control has a design assembly ToolboxBrowsableAttribute false.
    /// This control will not be in the Toolbox or Choose Items unless this assembly is loaded in the GAC.
    /// </summary>
    public class OnlyShowsInChooseItemsWhenInGAC : Control {
    }

    /// <summary>
    /// This control does NOT have a design assembly ToolboxBrowsableAttribute.
    /// WARNING:  This control will always be loaded in the Toolbox and will be visible in Choose Items.
    /// </summary>
    public class FrameworkElementAlwaysShows : FrameworkElement {
    }
}

Acme.Controls.Design.dll

The below design assembly applies to the above control assembly.

The ToolboxBrowsableAttribute can be created two ways, both syntaxs create the required attribute:

 //This should be in AssemblyInfo.cs - declaring here to make it obvious
//This attribute is used to determine which class to load to register metadata
[assembly: ProvideMetadata(typeof(Acme.Controls.Design.RegisterMetadata))]

namespace Acme.Controls.Design {

    internal class RegisterMetadata : IProvideAttributeTable {

        public Microsoft.Windows.Design.Metadata.AttributeTable AttributeTable {
            get {
                AcmeControlsAttributeTableBuilder obj = new AcmeControlsAttributeTableBuilder();
                return obj.CreateTable();
            }
        }
    }

    class AcmeControlsAttributeTableBuilder : AttributeTableBuilder {

        public AcmeControlsAttributeTableBuilder() {
            AddTypeAttributes(typeof(ToolboxBrowsableAttributeTrue), ToolboxBrowsableAttribute.Yes);
            AddTypeAttributes(typeof(OnlyShowsInChooseItemsWhenInGAC), ToolboxBrowsableAttribute.No);
            AddTypeAttributes(typeof(YouShouldNeverSeeMe), ToolboxBrowsableAttribute.No);
        }
        
        void AddTypeAttributes(Type type, params Attribute[] attribs) {
            base.AddCallback(type, builder => builder.AddCustomAttributes(attribs));
        }
    }
}

Scenario: TCI Toolbox Install

AssemblyFoldersEx Registry Entry

The following two registry entries will install the controls into the Toolbox under the Acme Toolbox tab.

[HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0\AssemblyFoldersEx\Acme]

@="c:\\Acme\\"

[HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0\AssemblyFoldersEx\Acme\Toolbox]

TabName="Acme"

How to Limit Types in the Toolbox and Choose Items Dialog when the Assembly is Not in the GAC

In the design assembly, add the ToolboxBrowsableAttribute.No to a public control assembly type's metadata to hide it. 

How to Limit Types in the Toolbox and Choose Items Dialog when the Assembly is in the GAC

In the design assembly, add the ToolboxBrowsableAttribute.No to a public control assembly type's metadata to hide it.

In the control assembly, decorate public types with the DesignTimeVisible(false)attribute to hide it.

Scenario: No TCI, Just Choose Items Dialog

How to Limit Types in the Toolbox and Choose Items Dialog when the Assembly is Not in the GAC

In the design assembly, add the ToolboxBrowsableAttribute.No to a public control assembly type's metadata to hide it.

How to Limit Types in the Toolbox and Choose Items Dialog when the Assembly is in the GAC

In the design assembly, add the ToolboxBrowsableAttribute.No to a public control assembly type's metadata to hide it.

In the control assembly, decorate public types with the DesignTimeVisible(false)attribute to hide it.

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above features enable your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett

Visual Studio Cider Team