Mar 31, 2009

How to Write Silverlight Design Time for All Designers: Visual Studio 2008, Blend 2; Blend 3, and Visual Studio 2010

Introduction

This is part of the series on design time implementation changes in Silverlight Toolkit March 2009 Release. This post focuses on the breaking changes in designer extensibility framework introduced in Silverlight 3/Blend 3/Visual Studio 2010, and how to develop Silverlight design time to support all designers: Visual Studio 2008/Blend 2, and Visual Studio 2010/Blend 3.

 

Silverlight 2 Design Time for Visual Studio 2008 and Blend 2

Visual Studio and Blend share the same designer extensibility framework, and use it for both WPF and Silverlight. WPF Designer Extensibility on MSDN is probably the best reference available for the designer extensibility framework. The December 2008 Release of Silverlight Toolkit is based on Silverlight 2 (aka SL2), and has designer support for Visual Studio 2008 (aka VS9) and Blend 2. It is a good real world example in demonstrating how to develop Silverlight 2 design time features for VS9 and Blend 2. My blog post Design Time Feature Implementation in Silverlight Toolkit explains in detail how it is done, and the implementation framework readers can use in their own design time implementation.

To recap, the Silverlight 2 design time framework for Visual Studio 2008 and Blend 2 in a nutshell:

  • MWD: the design time extensibility framework is exposed through a set of assemblies, most notably Microsoft.Windows.Design.dll, Microsoft.Windows.Design.Extensibility.dll, and Microsoft.Windows.Design.Interaction.dll. Collectively those assemblies are called MWD. They are installed under %DevEnvDir%\PublicAssemblies (C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies in 32bit OS, or  C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies in 64bit OS). They are also GAC-ed. Most design time projects need to reference those MWD dlls. Visual Studio 2008 and Blend 2 use MWD version 3.5.
    MWD in GAC
  • Naming Convention: Visual Studio and Blend load design time assemblies using a naming convention: for control assembly Foo.dll, VS and Blend will find its design time assemblies with the name Foo.Design.dll, Foo.VisualStudio.Design.dll, and Foo.Expression.Design.dll, in the same directory where Foo.dll is, or the Design sub directory. Visual Studio will load Foo.Design.dll and Foo.VisualStudio.Design.dll, while Blend will load Foo.Design.dll and Foo.Expression.Design.dll. So it is advised to put design time features shared across all designers in .Design.dll, and put Visual Studio and Blend specific design time features in .VisualStudio.Design.dll and .Expression.Design.dll respectively.
  • Entry Point: when Visual Studio or Blend loads a design time assembly, it uses reflection to find all classes that implement IRegisterMetadata, and calls its only method Register. Silverlight Toolkit December 2008 Release has a design time implementation framework detailed in previous blog post Design Time Feature Implementation in Silverlight Toolkit.

Below screenshots of Silverlight.Controls.Design.sln in Silverlight 2 Toolkit source in March 2009 Release demonstrates implementation of SL2 design time for VS9 and Blend 2 discussed above:
SL2 design projects

 

What Changed In Silverlight 3, Blend 3 and Visual Studio 2010

As stated in WPF Designer Extensibility Architecture on MSDN:

The WPF Designer supports the full extensibility framework. Expression Blend supports only property editors, metadata loading, and licensing. Blend does not support menu actions and adorners.

Blend 2 has above limited support for Silverlight design time too, but Visual Studio 2008 has little support for Silverlight design time (just icons, metadata loading for few attributes like ToolboxBrowsableAttribute): it is more a viewer than a designer. To have WPF parity for Silverlight design time support, Blend 3 and Visual Studio 2010 (aka VS10) have to introduce breaking changes to the designer extensibility framework (i.e. MWD), most notably:

  • MWD: most of the designer extensibility framework API stay the same, but their physical packaging changes: Microsoft.Windows.Design.dll is gone, and the version of all MWD assemblies changes from 3.5 to 4.0. Before Visual Studio 2010 Beta1, the only way to get the new MWD is via Blend 3 Preview, and its version is 3.7 instead of 4.0 for now:
    MWD in Blend 3
  • Entry Point: instead of reflect through IRegisterMetadata implementations, Blend 3 and Visual Studio 2010 use a new assembly attribute ProvideMetadataAttribute, and the metadataProviderType must implement IProvideAttributeTable:
    ProvideMetadataAttribute
  • Naming Convention: because of the breaking changes like MWD version and entry point, existing design time assemblies developed against 3.5 MWD will not load in Blend 3 and Visual Studio 2010, you have to write new design time against the new 4.0 MWD for Blend 3 and Visual Studio 2010. While this is OK for Blend (since you can only use Blend 3 with Silverlight 3 and Blend 2 with Silverlight 2), this creates a challenge for Visual Studio, since you can use Visual Studio 2008 for Silverlight 3 development, as well as Visual Studio 2010 for Silverlight 2 development.

Below table lists all supported scenarios and which version of MWD is used to load design time assemblies:

SL\Designer VS9 VS10 Blend2 Blend3
SL2 MWD3.5 MWD4.0 MWD3.5  
SL3 MWD3.5 MWD4.0   MWD4.0

We can’t build one design time assembly against two incompatible MWDs, so we have to create two separate design time assemblies, one against each MWD. Design time assemblies are loaded by name, and we can’t have two assemblies with the same name in the same location, so the design time assembly loading mechanism (i.e., the naming convention) has to change, to allow multiple versions of the same design time assembly coexist.

While waiting for the new naming convention to come out with Blend 3 and Visual Studio 2010 RTM, we can do something clever now to support both VS9 and VS10. Remember current naming convention allows Visual Studio and Blend each to load two design assemblies:

DLL\Designer Visual Studio Blend
Foo.Design.dll X X
Foo.VisualStudio.Design.dll X  
Foo.Expression.Design.dll   X

so we can build the two assemblies against different versions of MWD:

  • For Silverlight 3, we can have the shared .Design.dll build against MWD 4.0, so it can be loaded by both VS10 and Blend 3. We then have .VisualStudio.Design.dll build against MWD 3.5 and duplicate everything from shared .Design.dll, so it can be loaded by VS9. There is one minor issue though: we don’t have a place to put Visual Studio specific design time features for VS10, like using ToolboxBrowsableAttribute(false) to hide some controls from the increasingly crowded Visual Studio toolbox, since VS10 can’t load the .VisualStudio.Design.dll build against MWD 3.5. This will be solved with the new naming convention once Visual Studio 2010 RTM.
DLL\MWD\Designer MWD VS9 VS10 Blend3
Foo.Design.dll 4.0   X X
Foo.VisualStudio.Design.dll 3.5 X ?  
Foo.Expression.Design.dll 4.0     X
  • For Silverlight 2, follow the same approach: have the shared .Design.dll build against MWD 4.0, but have both .VisualStudio.Design.dll and .Expression.Design.dll build against MWD 3.5 and duplicate everything in shared .Design.dll. This way, both VS9 and Blend 2 will work just fine, but with the  same issue that there is no place to put Visual Studio specific features for VS10. Again, that will be solved with the new naming convention in VS10.
DLL\MWD\Designer MWD VS9 VS10 Blend2
Foo.Design.dll 4.0   X X
Foo.VisualStudio.Design.dll 3.5 X ?  
Foo.Expression.Design.dll 3.5     X

 

Design Time Feature Implementation in Silverlight 3 Toolkit

MWD

The design projects in Silverlight 3 Toolkit in March 2009 Release followed above mentioned scheme to support both Visual Studio 2008 and Visual Studio 2010, as well as Blend 3.

Download the March 2009 Release, unzip the source code, load Silverlight.Controls.Design.sln into Visual Studio 2008. Use the simpler Control.Input.Design project as example:

Controls.Input.Design.csproj in Silverlight 3 Toolkit Source

  • Design projects for VS9/Blend3 need to reference the new 4.0 MWD. Here we use pre-build event to invoke CopySystemWindows.bat to locate Blend 3 and copy the two  MWD dlls to Binaries directory.
  • Please note the minor changes to CopySystemWindows.bat file: we need to quote “%THIS_DIR%\Binaries\Blend3” (lines in yellow) to handle cases where there is a space in the path to the directory the source code is unzipped to.

If you don’t like the fragile CopySystemWindows.bat file or using build events, you can set Reference Paths to help Visual Studio find where the new MWD is, as shown below. The only caveat is that you need specify both %programfiles% and %programfiles(x86)% to make it build on both x86 and x64 machines.

Controls.Input.Design.csproj in Silverlight 3 Toolkit Source

The reference paths setting is persisted into the .csproj.user file:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ReferencePath>c:\Program Files\Microsoft Expression\Blend 3 Preview\;c:\Program Files (x86)\Microsoft Expression\Blend 3 Preview\</ReferencePath>
  </PropertyGroup>
</Project>

Metadata.cs

I use the same implementation framework as described in Design Time Feature Implementation in Silverlight Toolkit, with some minor changes:

Metadata.cs in Silverlight 3 Toolkit Source

  • I moved links to shared files Extensions.cs and MetadataBase.cs from Controls.Design.Common folder to under a solution folder with the same name;
  • Metadata.cs in .Design and .Expression.Design projects use the new entry point: use ProvideMetadata assembly attribute, and implement IProvideAttributeTable interface;
  • add note that everything in AddAttributes() method needs to be duplicated in corresponding .VisualStudio.Design project.

The .VisualStudio.Design projects still use the old IRegisterMetadata interface in MWD 3.5, but:
image

  • under Controls.Design folder are links to all *Metadata.cs files in corresponding .Design project;
  • AddAttributes() method duplicates the content of AddAttributes() method in corresponding .Design project.

Controls.Input.Expression.Design.csproj in Silverlight 3 Toolkit Source

 

Conclusion

While the breaking changes in MWD may cause some inconvenience, it is necessary to implement as rich a design time experience for Silverlight as for WPF. This post describes a way to handle the breaking changes and still support all existing designers: Visual Studio 2008, Blend 2, and Blend 3. Once Visual Studio 2010 is publicly available, I will blog about the new naming convention, and how Toolkit design time work in Visual Studio 2010. Stay tuned!

Mar 19, 2009

Silverlight Toolkit Design Time Features: March 2009 Release Update

Introduction

The March 2009 Release of Silverlight Toolkit has lots of new features and improvements. Among them, updates for design time features:

  • a new msi based installer that provides tight integration with Visual Studio and Blend out of box, thus making Silverlight development with the Toolkit much easier;
  • support both Silverlight 2 development with Visual Studio 2008 and Blend 2, and Silverlight 3 development with Visual Studio 2008 and Blend 3;
  • add design time features for the six new controls (Accordion, DomainUpDown, LayoutTransformer, TimePicker, TimeUpDown, TransitioningContentControl);
  • leverage the new design time extensibility framework in Blend 3 (and soon in Visual Studio 2010) and improve design time features for existing controls, like default intializers, AlternateContentPropertyAttribute, and custom editors, to provide a much better design experience, especially in Blend 3.

This post is an update for my prior post Design Time Features in Silverlight Toolkit.

Silverlight 2 Development with Visual Studio 2008 and Blend 2

Setup

http://silverlight.net/GetStarted/

  • Then follow step 4 to Silverlight Toolkit CodePlex page, click “Download the latest release” link:

http://www.codeplex.com/Silverlight

  • Click the “Silverlight 2 Toolkit March 2009 Installer” link, and run the msi: (You can also save the msi to your computer and run it later)

http://silverlight.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=20430

After the installer finishes, you will see Silverlight 2 Toolkit installed on your computer:

C:Program FilesMicrosoft SDKsSilverlightv2.0ToolkitMarch 2009LibrariesDesign

Please note:

  • there is a namespace (both CLR and xmlns prefix) and assembly name change from Microsoft.Windows.Controls in previous releases to System.Windows.Controls in this release. Please see Shawn Burke’s post Silverlight Toolkit March 2009 Release for a good explanation for the change and its implications for development with Silverlight Toolkit.
  • besides the existing four toolkit assemblies (Controls, Controls.Input, Control.DataVisualization, and Controls.Theming) in previous releases, there is a new assembly added in this release: Controls.Layout, which contained Accordion, LayoutTransfer, and TransitioningContentControls.
  • we still follow the same convention for design time assemblies: there are three design time assemblies for each run time assembly (.design, .expression.design, and .visualstudio.design), and all design time assemblies reside in the Design subfolder.

There is also a new Microsoft Silverlight 2 Toolkit March 2009 Start Menu item group to provide easy access to all Toolkit related information, like docs, samples, source code on local computer, and Silverlight Toolkit forums and CodePlex page on web:

Microsoft Silverlight 2 Toolkit March 2009 Start Menu item

Walkthrough

Let’s use a walkthrough on how to create a Chart control in Blend to demonstrate the design time features for Silverlight Toolkit:

  • Create a new Silverlight 2 Application project in Blend:

New Project Dialog

  • Add reference to the Toolkit assemblies: (Here I add all Toolkit assemblies, but only System.Windows.Controls.DataVisualization.Toolkit.dll is needed for this walkthrough)

Add Reference to Toolkit Assemblies

  • open Asset Library, click Custom Controls tab, and double click the Chart control:

Toolkit Controls in Asset Library

  • Add a Chart control to the design surface, set its Title property under Data Visualization category in Properties Panel:

Infotip, custom category, and custom editor

  • Click the New button next to DataContext property under Common Properties, select PointCollection from the Select Object dialog, and then click OK:

Create DataContext

  • In XAML editor, replace the generated XAML “<PointCollection />” to be like those highlighted in below screenshot, to provide some data for the Chart control to display:

Edit DataContext

  • Click the … button next to “Series (Collection)” property under Common Properties category, click “Add another item” button in the Series Collection Editor dialog, select ColumnSeries in Select Object dialog, and then click OK:

Create Series

  • Back to the Series Collection Editor dialog, set properties for the newly created ColumnSeries in the right Properties pane:
    • Set DependeptValuePath to X and IndependentValuePath to Y, both in Common Properties category
      Series Collection Editor
    • Click the rectangle to the right of ItemsSource property, select Data Binding… from the popped up context menu:
      Databinding for ItemsSource
    • Select the only item, PointCollection (Array) item, in Fields listbox in the Create Data Binding dialog, then click the Finish button:
      Create Data Binding Dialog
    • Back to the Series Collection Editor dialog again, notice the ItemsSource property is now surrounded with a yellow rectangle, indicating it now has a changed data binding value. Click OK to close the Series Collection Editor dialog:
      Series Collection Editor
  • We are back to Blend main window, and voila, we have a Chart control rendered nicely in the design view:

Yes!

We can hit F5 to build and run the project from Blend, or open the project in Visual Studio to continue editing the xaml and code. Notice in below screenshot that the Visual Studio toolbox is auto populated with Toolkit controls:

Visual Studio

Silverlight 3 Development with Visual Studio 2008 and Blend 3

Setup

Before you start, please read the Important developer notes on http://silverlight.net/getstarted/silverlight3/default.aspx#tools carefully (in below screenshot too).

After the installer finishes, you will see Silverlight 3 Beta SDK and Toolkit installed on your computer:

  • SDK:

Silverlight 3 SDK: C:Program FilesMicrosoft SDKsSilverlightv3.0LibrariesClientDesign

  • Toolkit:

Silverlight 3 Toolkit: C:Program FilesMicrosoft SDKsSilverlightv3.0ToolkitMarch 2009Libraries

And the Microsoft Silverlight 3 Toolkit March 2009 start menu item group for easy access to all Toolkit information:

image

Walkthrough

Now let’s do the same create a Chart control walkthrough, but this time with Blend 3:

  • Start Microsoft Expression Blend 3 Preview from Start menu, create a new Silverlight 3 Application + Website project:

Blend 3 New Project Dialog

  • Click the Asset Library, notice the Controls tab is pre-populated with Silverlight 3 runtime and SDK controls, including those used to be in Toolkit, like DockPanel, Expander, TreeView etc. Blend 3 populates Asset Library asynchronously, so you may notice a few seconds delay before the Controls tab is fully populated.

Asset Library, Controls Tab

  • Click the Custom Controls tab, notice it is pre-populated with Toolkit controls:

Asset Library, Custom Controls tab

  • Double click the Chart control, click and drag on the design surface, and voila, a Chart controls is created, initialized with some sample data, and nicely rendered. We had to go through a lot manual steps in Blend 2 to create the same result:

Chart Default Initializer

Please note in above screenshot:

  • in the projects panel on the right, reference to System.Windows.Controls.DavaVisualization.Toolkit.dll is automatically added;
  • in the xaml editor, the xmlns:chartingToolkit definition is automatically added
  • also notice a few Blend 3 new features, like custom icon for Chart control (in both Object and Timeline pane and Properties pane), default initializer that generates the initial xaml for the Chart control.

Since the Chart control is so easily created, let’s do a bit more in Blend 3 walkthrough.

  • Click Properties Tab on the right, and expand the Chart control in Objects and Timeline pane on the left:

Chart: AlternateContentPropertyAttributePlease note in above screenshot:

  • In Properties Panel, the little white dots to the right highlight the properties initialized by Chart control’s default initializer;
  • In Objects and Timeline Panel, there are LegendItems and Axes properties under Chart object, and IndependentAxis and DependentRangeAxis properties under ColumnSeries object. Those are called alternate content properties. Displaying them in the object hierarchy allows easy access to those properties at design time. For example, we can drag and drop a LinearAxis to the Axes property:

AlternateContentProperty

AlternateContentProperty

So comparing the same create a Chart control walkthrough in Blend 3 and Blend 2, we can see that Blend 3 a much better designer, and our design time assemblies for Blend 3 have leveraged many of the new design time extensibility capabilities, like default initializer and alternate content property, to greatly improve the design experience for Toolkit controls.

Now open the project in Visual Studio:

Visual Studio Design Experience

Please notice that:

  • The toolbox on the left is pre-populated with SDK and Toolkit controls.
  • The output windows at bottom right displays an error message about failed to load design assembly. Ignore it safely.

Design Experience in Visual Studio 2008 (Both Silverlight 2 and 3)

Toolkit design experience in Visual Studio is pretty much the same for both Silverlight 2 and Silverlight 3, so we can continue the following from either of above the two walkthroughs. For convenience sake, we will continue from the Silverlight 3 walkthrough immediately above.

Now drag and drop the Accordion control from toolbox to the XAML editor:

Visual Studio Design Experience

We can see that:

  • In XAML editor
    • xmlns:layoutToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"  is automatically added
    • <layoutToolkit:Accordion></layoutToolkit:Accordion> is automatically added
  • In Solution Explorer
    • references to System.Windows.Controls.Layout.Toolkit assembly, and the two assemblies it depends on, System.windows.Controls.Toolkit in Toolkit and System.Windows.Controls in SDK, are added automatically to the project

Now drag and drop a few controls from toolbox to XAML editor.

Visual Studio Design Experience

Please notice in above screenshot that:

  • in XAML editor
    • we can see that we dragged and dropped Calendar, AutoCompleteBox and NumericUpdown to the Accordion
    • appropriate xmlns definitions and xaml code are added automatically
  • In the Preview window
    • XAML code is properly rendered as we edit in XAML editor
  • In Code editor
    • notice the intellisense and infotip
    • Safely ignore the errors in Errors Window as we type in XAML or code editors before we finish the statement
  • In Solution Explorer:
    • references to needed assemblies are automatically added

Hit F5, and it builds and runs fine:

Visual Studio Design Experience

Credits

I certainly hope you are excited about the design experience improvements, since I implemented most of it :-) Jeff Wilcox implemented the installer, and Justin Angel wrote the spec for both the design time experience and installer. Many of my other colleagues contributed to the design experience too, especially RJ Boeke, Jafar Husain, and David Anson. Many thanks to the folks in Blend and Cider teams, particularly Unni Ravindranathan, Gary Linscott, Peter Blois; Brian Pepin, and Eric Fisk. Without them, none of the design experience improvements would be possible. And to Shawn Burke, for his support and emphasis on design time features, and deep involvement in solving key hard technical problems.

I will write a follow up post on design time implementation updates in March 2009 release. Stay tuned!