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

Comments

  • Anonymous
    February 22, 2010
    Karl, I just followed the steps listed above using the RC, and I'm still having all my WPF controls show in the toolbox.  I notice in the registry that I don't have  a v4.0 folder, instead there's a v4.0.30128 folder.  I put the information listed in the article under this folder, and it didn't work, and I even tried creating the v4.0 folder that the article mentions without any luck.   Any thoughts on why this won't work?  I can send you a build of the assemblies I'm using if that would help.

  • Anonymous
    February 22, 2010
    Geoffrey, I work with Karl and would love to get access to your assemblies and source code (if possible).  I just tried the information in this blog entry using the VS2010 RC and got expected results. Please send to the assbemly and source code to samharr @ microsoft.com at your earliest convience. Thank you, Sam Harrell VS WPF/SL Designer

  • Anonymous
    June 15, 2010
    Hi Karl, What steps should be made in order to support droping a custom Control from Toolbox to the Design Surface (SL and WPF). My control is in assembly that depends on other assemblies and for some reason when I drop it in the designer the needed assemblies are not added to the project. Is this scenario supported?

  • Anonymous
    June 15, 2010
    Hristo, Yes, your scenario is supported.  Please log a Microsoft Connect bug and include the project in the bug.  My team will get the bug and can help you.  You can log the bug as Private so that your code will not be seen by the public, just Microsoft support and our team. Sorry you are having a problem, have a nice day, Karl

  • Anonymous
    July 07, 2010
    Do you have a complete example that works with Silverlight 4 and VS 2010? Specifically: a) its unclear what the files are called and where things lie? b) what assemblies need to be included to add ProvideMetadata and IProvideAttributeTable?

  • Anonymous
    July 07, 2010
    Hi Karl, Do you have a simple example showing this for SL4 and VS 2010? My problem is:

  1. What kind of projects are Acme.Controls and Acme.Controls.Design?
  2. Assuming Acme.Controls targets silverlight and Acme.Controls.Design targets WPF how do you get the references to resolve between projects? I have yet to find a simple example for silverlight controls... Thanks
  • Anonymous
    July 08, 2010
    Tim and tmcconechy, This article only covers the known issue with respect to the GAC, Toolbox and TCI. This link points to a two part article that covers all of your questions:  blogs.msdn.com/.../wpf-silverlight-design-time-code-sharing-part-i.aspx This link also has many resources listed in the Downloads and More Information Links sections at the bottom of the article. After reviewing this informaiton, please post any questions you still have. Have a great day, Karl