Jan 21, 2009

How to Add an Toolbox Icon for Your Silverlight Control

Controls in Silverlight runtime (system.windows.dll) and SDK (system.windows.controls.dll) have nice toolbox icons in Visual Studio. December 2008 release of Silverlight Toolkit added that for Toolkit controls too, as described in my previous post Design Time Features in Silverlight Toolkit:

custom icons

This post explains how it is done in Silverlight 2 SDK, and in December 2008 release of the Silverlight Toolkit.

 

Control Icons in Run Time Assembly

The December 2008 Release of Silverlight Toolkit demonstrated how to embed toolbox icons for controls without using a design time assembly.

Open Silverlight.Controls.sln in Visual Studio (see previous post Design Time Feature Implementation in Silverlight Toolkit for more information on how to download the toolkit source):

Embed icons in run time assembly, visual studio view

Or open Controls.csproj in notepad:

<ItemGroup>
  <EmbeddedResource Include="Microsoft.Windows.ControlsAutoCompleteBox.Icon.png" />
  <EmbeddedResource Include="Microsoft.Windows.ControlsDockPanel.Icon.png" />
  <EmbeddedResource Include="Microsoft.Windows.ControlsExpander.Icon.png" />
  <EmbeddedResource Include="Microsoft.Windows.ControlsLabel.Icon.png" />
  <EmbeddedResource Include="Microsoft.Windows.ControlsTreeView.Icon.png" />
  <EmbeddedResource Include="Microsoft.Windows.ControlsViewbox.Icon.png" />
</ItemGroup>

Or open Microsoft.Windows.Controls.dll in reflector:

 Embed icons in run time assembly, reflector view

All three show that the custom toolbox icons are embedded resources in the run time assembly Microsoft.Windows.Controls.dll, with a particular naming convention. Take above Microsoft.Windows.Controls.Microsoft.Windows.AutoCompleteBox.Icon.png as an example:

  • The first Microsoft.Windows.Controls is the root namespace, specified in controls.csproj file with line: <RootNamespace>System.Windows.Controls</RootNamespace>
  • The next Microsoft.Windows.Controls.AutoCompleteBox is the fully qualified name of AutoCompleteBox class, including namespace but not assembly.
  • The rest of the name, Icon.png, specify the icon resource type, as will be explained more later.

Control Icons in Design Time Assembly

The Silverlight 2 SDK demonstrated the approach of embedding control icons in design time assembly.

Open System.Windows.Controls.Design.dll in reflector (it is installed under %ProgramFiles%Microsoft SDKsSilverlightv2.0LibrariesClient):

embed icon in design time assembly, reflector view

Take above Controls.Design.Icons.Calendar.bmp as an example:

  • Controls.Design is the root namespace, specified in its csproj file with line <RootNamespace>Controls.Design</RootNamespace>
  • Icons is the subfolder where the Calendar.bmp file is in source tree
  • Calendar.bmp is the name of the icon resource file in source tree

Control Icon Resource Naming Convention

So from above two examples, we can see that custom toolbox icons for controls are embedded resources in either run time assembly (so you don't need to ship a design time assembly), or design time assembly (so you have flexibility to change icons, like localize it for a different culture, without touching the run time assembly). The tools (Visual Studio 2008 SP1 for now) try to find the icons based on a special naming convention:

  1. Search for resources whose file name without extension matches the type name of the control, including the namespace with a “.icon[*].{XAML | BMP| PNG | GIF | JPG | JPEG}” .
    1. Note that subdirectories affect the namespace in which embedded resources are found. For example, the Toolkit icons are put under a Microsoft.Windows.Controls subfolder, to avoid putting this long string in all icon file names; while the SDK put all icons under a Icons subfolder.
    2. Supported extensions and file types are: XAML, BMP, GIF, JPG, JPEG and PNG
    3. Recommended image size for Bitmap based file formats is 64x64.
    4. The .icon[*] in the naming convention is optional and allows the Control Dev to specify multiple sizes of the image that is used as the icon. The match follows the following algorithm:
      1. Vector XAML
      2. If there is an exact match on size (both dimensions) use it
      3. Use the closest match based on size and aspect ratio
    5. If a given resource file is not valid XAML or a valid image file, the next match will be used until one is found.
  2. If an image is not found in the same namespace as the control, a loose match based on the type name alone will be searched for against all of the resources, as in the SDK case.
  3. Different hosts use different image sizes for their toolbox icon.
    1. Blend uses 24x24 for their large size and 12x12 for their small size (I don't think this is working in Blend 2 SP1)
    2. Cider (Visual Studio) uses 16x16

The blog post Specifying a Toolbox Icon for a Control in WPF Designer describes the naming convention in more details.

 

Hope this helps. Thanks!