Writing a design time experience for a Silverlight control

Writing a design time experience for a Silverlight control can be a bit intimidating (the experience for WPF controls remains unchanged from Blend 2 - just that you now have a ton more extensibility points - unless you wanted to re-use the same design-time code for the WPF and Silverlight versions of your controls). Let's try and understand how this works (because once you know the basics, its a breeze!).

Here is a project template that will help you get started immediately. All you need to do to use this project template is to unzip the contents to a folder like C:\Users\<username>\Documents\Expression\Blend 3\ProjectTemplates. Also, sorry - I did not have time to create a VB version yet.

The project created from this project template works as follows:

  • Two control libraries are created each time you create and instance of the project template. For example, lets assume the the user chose the name "MySilverlightControl" as the name for the control library. The two libraries that are created are called MySilverlightControl.dll, and MySilverlightControl.Design.dll.
  • The output path of MySilverlightControl.Design.csproj is set to copoy the library alongside MySilverlightControl.dll in a sub-folder called Design. This is identical to what you would do for a WPF control library - adding the design time library to a sub-folder prevents pollution of the "Add Reference" dialogs in the tools.
  • MySilverlightControl.Design.csproj is basically a WPF control library project (all the user interface components for the design time experience and metadata that you will specify for the controls are using the desktop CLR/WPF), and has the following:
    • A project-to-project reference to MySilverlightControl.csproj
    • Because MySilverlightControl.csproj is a Silverlight project (and because we want to use Silverlight types when we code the design time experience - more on this shortly), we need to add a reference to the Silverlight System.Windows.dll
    • References to the two Blend 3 / VS Next shared extensbility libraries - Microsoft.Windows.Design.Interaction.dll, and Microsoft.Windows.Design.Extensibility.dll. (Note: In Blend 2/VS 2008, we also had Microsoft.Windows.Design.dll - the APIs in this dll have been moved into the other two libraries, and MWD.dll is no more)
    • Because you have references to PresentationFramework.dll and System.Windows.dll, there is a conflict of types when you use a type like Button which exists in both. To help reslove this conflict for the compiler, we setup an alias for the Silverlight System.Windows.dll - TargetPlatform. Any type that is referenced using TargetPlatform::X.Y.Z is now resolved against the Silverlight assembly.
  • For both WPF and Silverlight control libraries, while the way you specify the metadata tables is still compatible with VS 2008 / Blend 2, the registration mechanism has a breaking change. You now need to use an assembly level attribute - ProvideMetadata - for this. You can find an example for this in MetadataStore.cs in the MySilverlightControl.Design.csproj.

While there are clear benefits to the approach we have chosen to support both WPF and Silverlight controls (same extensibility APIs so you don't have to learn two sets of APIs, ability to reuse the code for your design time experiences for WPF and Silverlight version of your controls by simply creating platform specific versions of the design time libraries), there are some pitfalls for advanced scenarios that can be easily avoided:

  • There are breaking changes to the APIs. Because Visual Studio 2008 SP1 GACs assemblies, unless you had a strong reference to the new assemblies, you might get compiler errors if the assemblies don't resolve to the new versions. Another option is to copy the assemblies locally into the project, and reference them from there. This issue will be addressed in a more convenient fashion shortly. 
  • It is very easy to to unknowingly pass in a platform specific object (say System.Windows.Point) into an API (for example, the ModelItem ones to set values) where the platform is not compatible. This can be easily avoided by using aliasing appropriately.
  • The .Net 3.5 SP1 WPF markup compiler (which comes into play when you try to define WPF UI for your desing-time - for example, a custom category layout for the property inspector or an adorner) does not play well with the aliasing system. To avoid this, consider separating the UI for the design time into a separate project that is a WPF only and has no references to the Silverlight assemblies.

Enjoy, and please do let me know if you run into issues as you work with Silverlight design time experiences so we can address them.