Showing posts with label Blend. Show all posts
Showing posts with label Blend. Show all posts

Apr 14, 2011

Silverlight 5 Beta Development Tools

Silverlight 5 Beta was announced at MIX11 yesterday. This blog post is an overview of Silverlight 5 development tools. To get started, download following components:

Recommended Downloads

 

VS/VWD 2010 SP1 + SL5Tools

SL4 development requires VS2010 or VWD2010 RTM and SL4Tools, and optionally Blend 4. VS2010 SP1 has SL4 support built in, so SL4Tools is not needed if you’ve already upgraded to VS2010 SP1. SL5 development requires VS2010 or VWD2010 SP1 and SL5Tools, and optionally Blend Preview for Silverlight 5.

Install

SL5 Beta Tools installs Silverlight 5 Beta Developer Runtime, SDK, Update to VS2010 SP1 (KB2502836), and WCF RIA Services V1.0 SP2 Preview.

image

Multi-targeting

Once installed, you can create SL5 projects like you used to with previous versions of SL:

image

SL5 projects can reference assemblies built against early versions of Silverlight. Below screenshot shows a SL5 project using SL4 SDK via Project->Add Reference…–>Browse:

image

And the result in .csproj file:

<Reference Include="System.Windows.Controls, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\..\..\..\..\..\..\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\System.Windows.Controls.dll</HintPath>
</Reference>

Please notice the HintPath and assembly version (Btw, SL5 increased assembly version from 2.0.5.0 to 5.0.5.0).

You can also upgrade existing SL4 projects to target SL5:

image

The upgrade changes <ProjectGuid> and <TargetFrameworkVersion> in .csproj, as well as upgrading all SDK references to SL5’s.

Binding Debugging

A popular new feature in SL5Tools is xaml binding debugging:

image

 

Blend Preview for Silverlight 5

Optionally, you can also install Blend Preview for Silverlight 5, which is basically Blend 4 with SL5 support:

image

And you can use both VS and Blend on the same SL5 project and switch between them:

image

image

 

Troubleshoot & Uninstall

VS2010 SP1, SL5Tools and Blend Preview install all take a long time, so please be patient. If you run into install issues, you may want to take a look at install logs in %temp% directory, and attach those logs when you report install issues to Microsoft:

C:\Users\ningz\AppData\Local\Temp>dir /b /o-d *silver*
Silverlight 5 Beta Tools for Visual Studio 2010 SP1_20110413_220121704.html
Silverlight 5 Beta Tools for Visual Studio 2010 SP1_20110413_220121704-MSI_RiaServices.msi.txt
Silverlight 5 Beta Tools for Visual Studio 2010 SP1_20110413_220121704-MSI_silverlight_sdk.msi.txt
Silverlight0.log

To uninstall Silverlight 5 tools, use control panel to uninstall each component individually:

  • SL5 runtime, SDK, RIA Services, Blend Preview

image

  • And Update to VS2010 (KB2502836) (please click “View installed updates” to see below)

image

 

Enjoy developing against Silverlight 5!

 

Nov 30, 2009

Silverlight Design Time Assemblies

Introduction

If you write Silverlight controls, you should consider writing design time assemblies for your controls too, for two simple reasons:

  • developer productivity: try to imagine Silverlight development without tools like Visual Studio or Blend! For custom controls, you may need to provide much of the design time experience for your controls in Visual Studio or Blend yourself.
  • designers: XAML and tools like Blend enable developers and designers work together. A key design criteria for Silverlight controls is to make sure designers can use them without writing a single line of code.

Design time experience usually includes (but not limited to) the following:

  1. Metadata for property window, like category, infotip, property editor, binding etc.
  2. Metadata for design surface, like initializer, adorner, context menu, adapters etc.
  3. Toolbox integration, like icons, control registration
  4. intellisense for code editor

Except intellisense (please see Add Rich Intellisense for Your Silverlight Controls) and control registration (please see Register Silverlight Controls with visual Studio and Blend), above design time experience are usually delivered through design time assemblies. Below I will discuss various approaches of delivering design time experiences, in increasing complexity and flexibility, and gradually introduce pieces of the naming convention of design time assemblies.

Runtime Assembly Only

The simplest way to deliver design time experience is to package design time code into the runtime assemblies, especially when design time metadata are meaningful at runtime too, like TypeConverterAttribute.

The pros and cons of this approach:

  • Pro: simple
    • no separate design time assemblies, simpler setup
    • design time attributes are specified directly on the runtime code, easier to maintain
  • Con: tight coupling of runtime and design time code
    • perf degradation because of useless design time code at runtime
    • design time dependencies (like MWDs and other VS/Blend assemblies) get dragged into runtime unnecessarily
    • can’t service runtime or design time independently
    • can’t support multiple designers (like both VS2008/Blend2 and VS2010/Blend3)
    So this approach is highly discouraged, unless there is strong justification for it.

Shared Design Time Assembly

So the revolutionary step forward is to decouple design time and runtime code, release and service them with separate assemblies. This opens up all kinds of possibilities. Of course, we need a way to link design time assemblies to their corresponding runtime assemblies, without introducing any unnecessary dependency or perf degradation to runtime assemblies. Hence the naming convention: if a runtime assembly Foo.dll is referenced in a Silverlight project, the designer (like Visual Studio and Blend) will first try to load design time information like icons (via another naming convention, see How to Add an Toolbox Icon for Your Silverlight Control) and design time metadata (via interface, like IRegisterMetadata for VS2008 and Blend2, or IProvideAttributeTable for VS2010 and Blend3. Please see How to Write Silverlight Design Time for All Designers: Visual Studio 2008, Blend 2; Blend 3, and Visual Studio 2010) from the runtime assembly; it will then look for a design time assembly by the name Foo.Design.dll in the same directory as Foo.dll; if found, the designer will try to load design time information from Foo.Design.dll as well.

Designer Specific Design Time Assembly

Visual Studio is mostly for developers, while Blend is mostly for designers, so they have difference requirements for design time experiences. Putting all design time code in one shared design time assembly introduces tight coupling among designers. So the naming convention is enhanced: for runtime assembly Foo.dll, there is a shared design time assembly Foo.Design.dll that’s loaded by all designers; each designer will also try to load its own design time assemblies, like Foo.VisualStudio.Design.dll for Visual Studio, and Foo.Expression.Design.dll for Blend. The designer specific design time assembly is loaded after the shared design time assembly. Third party designers can define their own designer specific design time assembly. 

Design Sub Folder

So to support both Visual Studio and Blend, each runtime assembly has three design time assemblies, in the same directory, and a package (like Silverlight SDK or Silverlight Toolkit) usually contains several runtime assemblies. So the directory gets a bit crowded. A minor improvement is to put the design time assemblies under a Design subfolder. So the naming convention is further enhanced: if a designer (like Visual Studio or Blend) can’t find corresponding design time assemblies in the same directory as a runtime assembly, it will look for them in the Design subfolder, if it exists. 

Support Multiple Versions of MWDs

Design time are built on top of designer extensibility framework, which consists of several dlls like Microsoft.Windows.Design.Extensibility.dll and Microsoft.Windows.Design.Interaction.dll. We usually call them collectively as MWDs. To make life more interesting, sometimes we have to introduce breaking changes to the extensibility framework, like VS2008 and Blend2 use MWD version 3.5, VS2010 and Blend3 use MWD version 4.0, and they are incompatible. So if you have a runtime assembly Foo.dll, and you want your users to be able to develop against it with both VS2008 and VS2010, you have to provide two sets of design time assemblies: one set built against v3.5 MWDs and used by VS2008, and another set built against v4.0 MWD and used by VS2010. The two sets of design time assemblies probably have a lot of code in common, while the one for VS2010 may have some new code to leverage the new functionalities exposed by VS2010. Since design time assemblies are loaded by name and you can’t have two files with the same name, so the naming convention is enhanced yet again:

for a runtime assembly Foo.dll, the shared design time assembly is named Foo.Design*.dll, the Visual Studio specific design time assembly is named Foo.VisualStudio.Design*.dll, and the Blend specific design time assembly is named Foo.Expression.Design*.dll, where * can be zero or more valid characters for file names. When a designer (like Visual Studio or Blend) tries to load a design time assembly and several fit the naming convention, zero or one will be loaded:

  • If the MWD version referenced by the design-time assembly has a different major version number than the designer’s MWD version, then the design-time assembly will not load and is bypassed.
  • If more than one design-time assembly is compatible with the designer’s MWD version, the Designer loads the one compiled against the highest MWD version that is less than or equal to the designer’s MWD version.

Please see Extensibility Series – WPF & Silverlight Design-Time Code Sharing – Part I and How to Write Silverlight Design Time for All Designers: Visual Studio 2008, Blend 2; Blend 3, and Visual Studio 2010 for more information.

Support Both WPF and Silverlight

To complicate life further, since WPF and Silverlight are so awfully similar, you may be tempted to try to write it once and run with both WPF and Silverlight. You are not alone. There are many articles on how to share source code and/or binaries across Silverlight and WPF. We’d like to do that for design time assemblies too. One approach is to make most of the design time assemblies platform agnostic, and limit platform specific (WPF or Silverlight) code and references to a small platform specific assembly. Please see Extensibility Series – WPF & Silverlight Design-Time Code Sharing – Part I for more information on this.

Last One Wins

The same design time metadata for a class or its member can be specified multiple times in multiple design time assemblies, which allows the shared design time assembly to specific the default/common behavior and then designer specific design time assemblies to override it if necessary. The same design time metadata can also be specified multiple times within a single design time assembly (please see Design Time Feature Implementation in Silverlight Toolkit as an example, where DescriptionAttribute for a class or its property can be added by AddDescriptions, AddAttributes and AddTables methods). So we need to know which metadata wins. The simplest and most logic design is that last one wins. This is mostly true but not always. Sometimes the result is un-deterministic when the same design time metadata is specified several times but with different values.

Feedback

Devil is in the details! Feedbacks are always appreciated. Please let me know what issues you run into, what requests/improvements you’d like to make, for both design times experience and designer extensibility framework. Thanks!

 

Sep 29, 2009

Silverlight Design Time: Toolkit July 2009 Release Update

I have been very busy and haven’t post for a while, so this is a quick late post on Toolkit July 2009 Release. This release is the last Toolkit release for Silverlight 2: when a new version of Silverlight RTMs, we drop support for the previous version, so each Toolkit release needs to support at most two versions of Silverlight. As for design time feature updates, there have been a lot of improvements over March 2009 Release. I will use a simple walkthrough to highlight a few noticeable new features:

  • Install Silverlight 3, Blend 3 and Toolkit from http://silverlight.net/getstarted/
  • Open Blend 3, create a new Silverlight 3 Application project
  • Open Asset Library, notice few improvements:
    • the new Asset Library. See Unni’s blog The Blend 3 Asset Library for more info. 
    • the nicer icons and more informative infotip

Blend 3 Asset Library

  • Add an Expander control, and set it as the new active container:
Pin Active Container
  • Add a DatePicker to the Expander, notice that both the DatePicker and its Calendar drop down are shown, even though both Expander’s IsExpanded and DatePicker’s IsDropDownOpen are false.

image

  • Select LayoutRoot so Expander and the nest DatePicker are no longer selected, notice that both are now collapsed.

image

Visual Studio ToolboxOpen the project in Visual Studio,notice that the Toolbox is populated with lots of controls from Silverlight SDK and Toolkit, with nice icons.

 

So far, design time features for Silverlight are mostly exposed through Blend. This will change with next beta of Visual Studio 2010, which will come out soon, according to this Visual Studio Magazine article. Stay tuned!

Apr 30, 2009

Register Silverlight Controls with Visual Studio and Blend

 Introduction

This is part of the series on design time implementation changes in Silverlight Toolkit March 2009 Release. This post illustrates the integration of Silverlight Toolkit with Visual Studio and Blend 3 after running Silverlight 3 Toolkit March 2009 Installer, and explains how it is done, so you can register your own Silverlight controls with Visual Studio and Blend too.

Blend Integration

After installing Silverlight 3 Beta1 Tools, Blend 3 Preview, and Silverlight 3 Toolkit March 2009 (please see Silverlight Toolkit Design Time Features: March 2009 Release Update, Silverlight 3 Development with Visual Studio 2008 and Blend 3 section for more information), create a Silverlight 3 Application from Blend 3, we can see that Silverlight Toolkit controls show up automatically in Asset Library:

Toolkit Controls in Asset Library, Controls Tab

Toolkit Controls in Asset Library, Custom Controls Tab 

User can drag and drop Toolkit controls from Asset Library to design or xaml view, and Blend will automatically add assembly reference, xmlns prefix and xaml code, very convenient:

Drag and Drop Chart control from Asset Library

Visual Studio Integration

Open the project in Visual Studio, we can see that Toolkit controls show up automatically in Visual Studio Toolbox, and user can drag and drop controls from Toolbox to design or xaml view as well:

Toolkit Controls in Visual Studio Toolbox 

Besides Toolbox, Toolkit assemblies also show up in Add Reference Dialog:

Add Reference Dialog

and Choose Toolbox Items Dialog:

image

 Implementation

The integration with Visual Studio and Blend is done via registry. If you open “Silverlight 3 Toolkit March 2009.msi” in Orca, you can see the registration magic:

Silverlight 3 Toolkit March 2009.msi in Orca

Register with Visual Studio

AssemblyFoldersEx

Registering with Visual Studio is mostly done via [HKLM|HKCU]\Software\Microsoft\Microsoft SDKs\Silverlight\v3.0\AssemblyFoldersEx:

Visual Studio Registration

The References in Visual Studio page has very good explanation on AssemblyFoldersEx and reference resolution. It is a bit outdate, and is about .net instead of Silverlight, but it is mostly right for Silverlight too. I duplicated the registration schema section below, and modified it to fit Silverlight. Text in small italic fonts are purely hypothetical, meaning: it doesn’t work for Silverlight today; I have it here simply because it is in originally text, works for .NET, and seems making sense for Silverlight to duplicate or to be consistent with .Net.

Registration Schema

Assembly directories can be added to the registry so that the build process can resolve references to assemblies in those directories. Here’s an example of the registry schema.

[HKLM | HKCU]\SOFTWARE\MICROSOFT\Silverlight\

  v3.0

    AssemblyFoldersEx

      Silverlight Toolkit

        @Default = C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Toolkit\March 2009\Libraries\

        @Description = Silverlight 3 Toolkit March 2009

        20090401

          @Default = C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Toolkit\March 2009\20090401

          @Description = April Fool’s Updates

In the above example, there are several interesting fields.

(1) AssemblyFolderBase – The registry path "\SOFTWARE\MICROSOFT\Silverlight" indicates the target framework platform. Typical values for this property are:

\SOFTWARE\MICROSOFT\Silverlight(default) – for Silverlight

\SOFTWARE\MICROSOFT\.NetCompactFramework– for .NET Compact Framework

(2) FrameworkVersion – The version of the frameworks that this component is meant to work against.

(3) AssemblyFoldersSuffix – Describes the sub-target, examples include:

AssemblyFoldersEx (default) – for Silverlight

PocketPC\AssemblyFoldersEx – for the .NET Compact Framework for Pocket PC

SmartPhone\AssemblyFoldersEx – for the .NET Compact Framework for SmartPhone

WindowsCE\AssemblyFoldersEx – for the .NET Compact Framework for WindowsCE

(4) ControlName – The name of the control. In the example above, “Silverlight 3 Toolkit March 2009”. The control vendor chooses this name.

(5) ServicingCode – For service packs that update the same component. In the above example, “20090401”. The control vendor chooses this name.

Toolbox Controls Installer

Jim Nakashima blogged about Toolbox Controls Installer for WPF controls in his post Have you seen the Toolbox Controls Installer? in 2007. Toolbox Controls Installer package is now part of Visual Studio 2008, and kind of works, with a bug that will be fixed in Visual Studio 2010. It can be tweaked to work for Silverlight controls too: set string registry value SilverlightControls instead of WPFControls to 1.

I am working with various teams inside Microsoft to improve the Visual Studio registration story for Silverlight controls. All feedbacks and suggestions are welcome!

 Register with Blend

Registering with Blend is via HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Expression\Blend\v3.0\Toolbox\Silverlight\v3.0:

Blend Registration

Unni Ravindranathan’s blog post Blend 3 Extensibility has more information about this mechanism. One caveat: if the registered assemblies depend on other assemblies, those other assemblies need to be in the same directory as registered assemblies, or registered with AssemblyFoldersEx mentioned above. 

Conclusion

Registration with Visual Studio and Blend makes Silverlight Toolkit controls a lot easier to use for developers. We are constantly looking at improving the registration mechanism in hope to make it simple and consistent across designers (Visual Studio and Blend) and technologies (WPF and Silverlight). All feedbacks are welcome!

Apr 22, 2009

Add Rich Intellisense for Your Silverlight Controls

Introduction

This is part of the series on design time implementation changes in Silverlight Toolkit March 2009 Release. This post illustrates the rich intellisense support for Silverlight Toolkit, and explains implementation workflow from xmldoc in source to infotip in intellisense xml file and design assemblies.

Intellisense

Silverlight Toolkit has rich Intellisense in code and XAML editors in both Visual Studio and Blend:

  • Visual Studio Code Editor:
    VS2008 Code Editor Intellisense
  • Blend 3 Code Editor:
    Blend 3 Code Editor Intellisense
  • Blend 3 XAML editor:
    Blend 3 Xaml Editor Intellisense

Visual Studio XAML editor has intellisense too, but no infotip: Visual Studio Xaml Editor Intellisense

Implementation

Code Editor Intellisense Infotip from XML Files

The intellisense infotips in code editors in Visual Studio and Blend come from intellisense xml files installed under Silverlight SDK and Toolkit directories:

Intellisense xml files installed

Localization

Those intellisense xml files can be localized. If you install localized Visual Studio and localized Silverlight SDK, you will see localized infotips, which is a great help for those who don’t speak English. Below is the screenshot of Visual Studio running with Simplified Chinese language and simplified Chinese version of Silverlight Tools for Visual Studio SP1:

Chinese VS and Infotip

The Chinese infotip is from localized System.Windows.Controls.xml under zh-CHS sub directory:

C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client>dir/s /b system.windows.controls.xml
C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client\system.windows.controls.xml
C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Client\zh-CHS\system.windows.controls.xml

 

XAML Editor Intellisense Infotip from Design Assemblies

The intellisense infotips in Blend 3 XAML editor come from a different mechanism: they come from DescriptionAttribute implemented by design dlls installed under the Design subdirectory:

SDK Design folder

So it is the same as infotips in Blend Properties panel (please see Design Time Features in Silverlight Toolkit for more information):

Blend Property Inspector Infotip

xmldoc comment –> intellisense xml file –> DescriptionAttribute in design assembly

All those infotips come from xml documentation comments in source code, as seen from below screenshot:

Workflow of xmldoc to infotip

  1. we put xmldoc comments in source code
  2. build generates .xml files from those xmldoc comments
  3. the generated .xml files are embedded in design dlls (see Design Time Feature Implementation in Silverlight Toolkit for more information)
  4. the control dlls, design dlls, and xml files are installed by SDK and Toolkit setup

Conclusion

This post describes the rich intellisense support of Silverlight Toolkit and its implementation workflow from xmldoc comments to intellisense xml files to design dlls. Good commenting pays!

Apr 3, 2009

Property Value Editors for Silverlight Controls

Introduction

This is part of the series on design time implementation changes in Silverlight Toolkit March 2009 Release. This post discusses how to enhance property editing experience for Silverlight controls using property value editor and type converter. I will start with describing the overall property editing architecture in WPF/Silverlight designer extensibility framework, then use examples in  Silverlight Toolkit March 2009 Release to demonstrate how it is done, and unique issues/tricks in Silverlight design time development.

Property Editing Architecture

Visually editing object properties is an important part of designers. Designers usually don’t know how to render properties of custom type (struct, class or interface), much less to provide an nice editing user interface. Control developers usually need to provide TypeConverter, PropertyValueEditor, or both, to provide rendering/editing UI and XAML serialization for properties of custom types.

The designer extensibility framework defines three types of property value editor: inline editor, extended editor, and dialog editor, each implemented by a class:

PropertyValueEditor class diagram

Editing UI of those editors are defined by DataTemplate. The property being edited is exposed to editor as DataContext of PropertyValue type. Editor UI usually bind to the underlying property being edited via one of the three properties of PropertyValue: Value, StringValue, or Collection.

PropertyValueEditor

PropertyValueEditor holds a single inline editor defined by InlineEditorTemplate property. Inline editor appears inside the properties window. Below is an simple example of InlineEditorTemplate that uses a TextBox to display and edit a property:

<DataTemplate x:Key="TextBoxEditor">
   <TextBox Text="{Binding Path=Value}"/>
</DataTemplate>
 

ExtendedPropertyValueEditor

ExtendedPropertyValueEditor has two editors: an inline editor inherited from PropertyValueEditor, and an additional extended editor defined by the ExtendedEditorTemplate property. The extended editor is usually popped up by inline editor via PropertyValueEditorCommands.ShowExtendedPinnedEditor or PropertyValueEditorCommands.ShowExtendedPopupEditor command. Below is a simple example: the inline editor is a button; when clicked, it pops up the extended editor that uses a Slider to display and edit the underlying property.
<DataTemplate x:Key="inlineEditor">
   <Button Content="..." Command="{x:Static PropertyEditing:PropertyValueEditorCommands.ShowDialogEditor}"/>
</DataTemplate>
<DataTemplate x:Key="extendedEditor" xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design.Interaction">
   <Slider x:Name="slider" Value="{Binding Path=Value}" />
</DataTemplate>
 

DialogPropertyValueEditor

DialogPropertyValueEditor has two editors too: the inline editor inherited from PropertyValueEditor, and an additional dialog editor defined by DialogEditorTemplate property. The dialog editor is usually popped up by inline editor via PropertyValueEditorCommands.ShowDialogEditor command. Below is a simple example:

<DataTemplate x:Key="inlineEditor">
   <Button Content="..." Command="{x:Static PropertyEditing:PropertyValueEditorCommands.ShowDialogEditor}"/>
</DataTemplate>
<DataTemplate x:Key="dialogEditor" xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design">
   <Grid>
       <Grid.ColumnDefinitions>
           <ColumnDefinition Width="Auto" />
           <ColumnDefinition Width="*" />
       </Grid.ColumnDefinitions>
       <Grid.RowDefinitions>
           <RowDefinition Height="*"/>
           <RowDefinition Height="*"/>
       </Grid.RowDefinitions>
       <TextBlock Text="User Name:" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,4"/>
       <TextBox Text="{Binding Path=Value}" VerticalAlignment="Center" HorizontalAlignment="Stretch" Margin="0,0,4,4" Grid.Column="1"/>
   </Grid>
</DataTemplate>

Implement Custom Property Editor

To implement a custom property editor for a Silverlight control:

  • implement a custom property editor class
  • Associate the custom property editor with a property of a Silverlight control via a AddCustomAttributes call, something like
    attributeTableBuilder.AddCustomAttributes(
       typeof(MyControl),
       "MyProperty",
       new PropertyValueEditor.CreateEditorAttribute(typeof(MyValueEditor)));
    A correctly implemented property value editor must satisfy the following requirements:
  • The property value editor must be designed so that the inline editor and extended editor parts can be used independently.
  • A property value editor must not store state. Property value editors are stateless, might be cached by a host implementation, and can be re-used across multiple property values.
  • A property value editor must not assume that only one value editor part (view/inline/extended) control is active at a given time. For example, a dialog box could have the view part, inline part, and extended UI part active at the same time.
  • A control implemented as part of a property value editor must not store state. A control implemented as part of a value editor should not assume that it will only be bound to one property value. Controls may be recycled to change different property values. Any information that is cached should be flushed if the data model is updated.
  • A control implemented as part of a property value editor must not make any assumptions about the host or its parent controls. The only communication mechanisms that should be used are the PropertyValue data model, by way of the DataContext, and the standard set of commands.
     

Reference Both WPF and Silverlight Assemblies

A design assembly is a .NET/WPF assembly loaded by Visual Studio or Blend, but it usually needs to reference Silverlight assemblies (at least the Silverlight control assembly it provides design time features for). This can create reference ambiguity for design assembly project: it sometimes needs to reference the same fully qualified type in both WPF and Silverlight, say System.Windows.FrameworkElement in both PresentationFramework.dll of WPF and System.Windows.dll of Silverlight. To avoid confusing Visual Studio, you can use extern alias to distinguish WPF and Silverlight references.

For example, see the screenshot below for Controls.DataVisualization.Toolkit.Design project in Silverlight 3 Toolkit in March 2009 Release:

image

  • the project references both PresentationFramework and System.Windows, but System.Windows is under Silverlight alias, instead of the default global alias. The System.Windows reference under Silverlight alias is persisted in .csproj file as below:
    <Reference Include="System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, processorArchitecture=MSIL">
     <SpecificVersion>False</SpecificVersion>
     <HintPath>..\Binaries\System.Windows.dll</HintPath>
     <Private>False</Private>
     <Aliases>Silverlight</Aliases>
    </Reference>
  • in source code, we add
    extern alias Silverlight;
    using SSW = Silverlight::System.Windows;

    and reference Silverlight’s FrameworkElement via SSW::FrameworkElement.

TextBoxEditor

There is a inline editor TextBoxEditor in Controls.DataVisualization.Toolkit.Design project for displaying and editing Title property of object type for  [Area|Bar|Bubble|Column|Line|Pie|Scatter]Series and Chart controls, as shown below:

TextBoxEditor

Text filled in Title field in Properties window on the right shows up automatically in XAML and design views in the middle.

The implementation of TextBoxEditor followed the steps outlined before:

TextBoxEditor.cs

TextBoxEditor.cs:

// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using Microsoft.Windows.Design.PropertyEditing;
using System.Windows;
using System.Windows.Data;

namespace System.Windows.Controls.DataVisualization.Design
{
   /// <summary>
   /// Simple TextBox inline editor.
   /// </summary>
   public partial class TextBoxEditor : PropertyValueEditor
   {
       /// <summary>
       /// Preserve the constructor prototype from PropertyValueEditor.
       /// </summary>
       /// <param name="inlineEditorTemplate">Inline editor template.</param>
       public TextBoxEditor(DataTemplate inlineEditorTemplate)
           : base(inlineEditorTemplate)
       { }

       /// <summary>
       /// Default constructor builds the default TextBox inline editor template.
       /// </summary>
       public TextBoxEditor()
       {
           FrameworkElementFactory textBox = new FrameworkElementFactory(typeof(TextBox));
           Binding binding = new Binding();
           binding.Path = new PropertyPath("Value");
           binding.Mode = BindingMode.TwoWay;
           textBox.SetBinding(TextBox.TextProperty, binding);

           DataTemplate dt = new DataTemplate();
           dt.VisualTree = textBox;

           InlineEditorTemplate = dt;
       }
   }
}

CultureInfoEditor

My colleague RJ wrote inline editor CultureInfoEditor for TimePicker.Culture property, because the default editing experience for CultureInfo in Blend leads to invalid XAML. Below screenshot shows the CultureInfoEditor uses a ComboBox to display all CultureInfo and generates right XAML.

CultureInfoEditor

CultureInfoEditor is a more complex example than TextBoxEditor, really shows how the underlying property is associated with editor via DataContext property.

CultureInfoEditor.cs:

// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System.Reflection;
using Microsoft.Windows.Design.PropertyEditing;
using System.Globalization;
using System.ComponentModel;

namespace System.Windows.Controls.Input.Design
{
   /// <summary>
   /// Editor for CultureInfo.
   /// </summary>
   /// <remarks>Currently does not support binding from xaml to the editor.</remarks>
   public class CultureInfoEditor : PropertyValueEditor
   {
       /// <summary>
       /// The ComboBox being used to edit the value.
       /// </summary>
       private ComboBox _owner;

       /// <summary>
       /// Preserve the constructor prototype from PropertyValueEditor.
       /// </summary>
       /// <param name="inlineEditorTemplate">Inline editor template.</param>
       public CultureInfoEditor(DataTemplate inlineEditorTemplate)
           : base(inlineEditorTemplate)
       { }

       /// <summary>
       /// Default constructor builds a ComboBox inline editor template.
       /// </summary>
       public CultureInfoEditor()
       {
           // not using databinding here because Silverlight does not support
           // the WPF CultureConverter that is used by Blend.
           FrameworkElementFactory comboBox = new FrameworkElementFactory(typeof(ComboBox));
           comboBox.AddHandler(
               ComboBox.LoadedEvent,
               new RoutedEventHandler(
                   (sender, e) =>
                   {
                       _owner = (ComboBox) sender;
                       _owner.SelectionChanged += EditorSelectionChanged;
                       INotifyPropertyChanged data = _owner.DataContext as INotifyPropertyChanged;
                       if (data != null)
                       {
                           data.PropertyChanged += DatacontextPropertyChanged;
                       }
                       _owner.DataContextChanged += CultureDatacontextChanged;
                   }));

           comboBox.SetValue(ComboBox.IsEditableProperty, false);
           comboBox.SetValue(ComboBox.DisplayMemberPathProperty, "DisplayName");
           comboBox.SetValue(ComboBox.ItemsSourceProperty, CultureInfo.GetCultures(CultureTypes.SpecificCultures));
           DataTemplate dt = new DataTemplate();
           dt.VisualTree = comboBox;

           InlineEditorTemplate = dt;
       }

       /// <summary>
       /// Handles the SelectionChanged event of the owner control.
       /// </summary>
       /// <param name="sender">The source of the event.</param>
       /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> 
       /// instance containing the event data.</param>
       private void EditorSelectionChanged(object sender, SelectionChangedEventArgs e)
       {
           // serialize with name.
               object DataContext = _owner.DataContext;
               DataContext
                   .GetType()
                   .GetProperty("Value", BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty)
                   .SetValue(DataContext, ((CultureInfo)_owner.SelectedItem).Name, new object[] { });
       }

       /// <summary>
       /// Handles the PropertyChanged event of the context object.
       /// </summary>
       /// <param name="sender">The source of the event.</param>
       /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
       private void DatacontextPropertyChanged(object sender, PropertyChangedEventArgs e)
       {
           // deserialize from name.
           if (e.PropertyName == "Value")
           {
               object value = sender
                   .GetType()
                   .GetProperty("Value", BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty)
                   .GetValue(sender, new object[] { });

               if (value != null)
               {
                   if (value is string)
                   {
                       CultureInfo setCulture = new CultureInfo(value.ToString());
                       _owner.SelectedItem = setCulture;
                   }
               }
           }
       }

       /// <summary>
       /// Called when the context is changed.
       /// </summary>
       /// <param name="sender">The sender.</param>
       /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
       private void CultureDatacontextChanged(object sender, DependencyPropertyChangedEventArgs e)
       {
           INotifyPropertyChanged old = e.OldValue as INotifyPropertyChanged;
           if (old != null)
           {
               old.PropertyChanged -= DatacontextPropertyChanged;
           }
           INotifyPropertyChanged newDataContext = e.NewValue as INotifyPropertyChanged;
           if (newDataContext != null)
           {
               newDataContext.PropertyChanged += DatacontextPropertyChanged;
           }
       }
   }
}

ExpandableObjectConverter

As discussed at the beginning, besides custom property value editors, sometimes you can use appropriate type converter to provide good editing experience and XAML serialization. One example is ColumnSeries.DependentRangeAxis: it is of IRangeAxis type, Blend doesn’t know how to edit it, so it shows DependentRangeAxis as read only in Properties Panel. By associating ExpandableObjectConverter to ColumnSeries.DependentRangeAxis:

b.AddCustomAttributes(
   Extensions.GetMemberName<ColumnSeries>(x => x.DependentRangeAxis),
   new TypeConverterAttribute(typeof(ExpandableObjectConverter)));
b.AddCustomAttributes(
   Extensions.GetMemberName<ColumnSeries>(x => x.IndependentAxis),
   new TypeConverterAttribute(typeof(ExpandableObjectConverter)));

Blend displays a New button next to this property in Properties Panel; when clicked, it pops up the Select Object dialog, filtered with the property’s type IRangeAxis:

ExpandableObjectConverter

Conclusion

Blend and Silverlight together allow designers to create amazing UI against real controls directly, so it is very important that control developers take designer experience as part of overall control design and implementation. Having a custom property editor that provides nice editing UI and generates correct XAML is an important part of the designer experience. Hopefully this post helps you understand how to create custom property editors. Thanks!

Dec 24, 2008

Quick Blend Tutorial for Developers

Introduction

XAML is an major invention of WPF, and XMAL "programming" is an important part of WPF/Silverlight development. Even though XAML is XML and can be authored manually, it is mostly designed for tools, so good authoring tools are more important to XAML than to other languages like C# or HTML. Blend to XAML is what Visual Studio is to C#. There are many good tutorials and documents for Blend, like Jesse Liberty's Expression Blend for Developers. This post is more like "Learn Blend in 15 Minutes", aiming to give an quick overview and tutorial of Blend to developers who are authoring XAML mostly in Visual Studio or notepad, and so they will be interested and know how to get started in using Blend.

Project Management

Blend duplicates a lot of Visual Studio functionality and has great integration with it. It is very common (or even recommended, should I say) to have a WPF/Silverlight project open in both Blend and Visual Studio, using Blend for XAML authoring and Visual Studio for C# coding (or whatever language you prefer), and using either or both for project management.

Project manage in Blend is very similar to that in Visual Studio, via menu, Project Panel and Results Panel:
Blend: Project Management

  • Menu: the File, Edit, Project and Help menus are very similar to those in Visual Studio. Through those menus, you can create/open WPF/Silverlight projects, add items/references etc, and even build and run the solution, just like in Visual Studio.
    File Menu Project Menu
  • Project Panel: it is very similar to Visual Studio's Solution Explorer. You can right click on any .xaml/.cs file in the project panel and select "Edit in Visual Studio", and the project and the selected file will be open in Visual Studio for editing.
    Edit in Visual Studio Context Menu
  • Result Panel: the Output tab and Error tab are similar to Output window and Error List window in Visual Studio.

UI Authoring

UI authoring is done mostly via three panels: 
Blend: UI Authoring

  • Objects and Timeline Panel: the objects panel makes the logical tree structure very clear. It is easy to navigate the logical tree by expanding/collapsing/selecting an element in the tree, or restructure the tree by dragging and dropping elements along the tree. The selected element is highlighted in the objects panel, and in both the design view and xaml view of the documents panel; the properties panel displays the properties and events of the selected element. The internal node with yellow border (LayoutRoot in above screenshot) is the current default container.
  • Documents Panel: the documents panel is a tabbed window, with one tab for each open xaml file. It has a design view and a xaml view for each file.
    • You can use the tabs at the top of the documents window to switch among open documents or close documents(only one tab in above screenshot, since only one file page.xaml is open.).
    • You can switch among Design view, XAML view, or Split view of the selected document. You can also set the default document view in Tools -> Options -> Documents:
      Documents View Options
    • There is a breadcrumb control at the top of the design view (also called artboard) to show the logic tree path of the selected element. This is another way to navigate the logical tree besides the objects panel, and to switch among authoring modes as we will see shortly.
    • You can zoom the design view by
      • select the zoom icon from the toolbox, then click or alt click on the artboard;
      • use the zoom combobox right below the artboard: zoom combobox
      • use the View menu items or their shortcut keys: View menu
    • The design view is a WYSIWYG designer, where you can drag and drop an element from the toolbox or Asset Library along the left border of Blend window:
      Toolbox  Asset Library
    • The XAML view allows direct XAML authoring. It doesn't have IntelliSense yet, but you can use the design view and the error tab in the Results panel below to correct errors while you type.
  • Properties Panel: properties panel has two views: properties and events, indicated by two buttons at the top right corner of the panel.
    • In properties view: 
      image
      • properties of the selected element is grouped into categories, like Layout, Common Properties;
      • properties usually have helpful tooltip, like Content property tooltip in above screenshot;
      • properties usually have inline/extended/dialog editor(s) to help user pick a value, like the value of HorizontalAlignment property in above screenshot can be set by clicking one of the four buttons, instead of typing in values like "Center" in XAML view directly;
      • if you give a property a value (so it no longer takes the default value), the little square to its right will become white, like the Alignment properties in above screenshot;
      • you can click the down arrow (which has "Show advanced properties" tooltip) in most categories to see more properties of that category;
      • you can find a property quickly by typing part of its name in the Search box at the top of the properties panel:
        Search box in Properties Panel
    • In events view:
      Properties Panel: Events view
      • you can type the name of the event handler for an event, and Blend will open the project in Visual Studio, with a prototype implementation of the event handler in the code behind file:
        Blend opens Visual Studio for event handler coding
         

Animation Authoring

To create an animation, click the plus sign in Objects and Timeline panel, the "Create Storyboard Resource" dialog will pop up, asking for the name of the new storyboard:
Create Storyboard Resource

Blend then enters timeline recording mode. Let's create an animation that will double the size of the button. The key steps in creating an animation:

  1. create a keyframe, by first dragging the yellow timeline to a keytime, and then clicking the "Record Keyframe" green plus button;
  2. edit properties of UI elements at keytime, as described in the above UI Authoring section;
  3. repeat steps 1 and 2 for each keyframe;

As we can see in below screenshot:

  • in Objects and Timeline Panel:
    • the name of the timeline being edited: Storyboard1;
    • the keyframe being edited: keytime is 1 second, indicated by the yellow timeline;
    • the double arrow icons to the left of the nodes in the objects panel (button, RenderTransform, Scale, ScaleX, ScaleY in below screenshot) and the white dots along the timeline in the timeline panel show property changes for objects at the keytime ;
    • we can use the play controls at the top of the timeline panel, or drag the yellow timeline, to run the animation;
  • in Artboard of Documents Panel:
    • the red border, red recording button, and the red label "Timeline recording is on" all indicate Blend is in timeline recording mode;
    • you can click the red recording button to stop the recording mode and switch back to UI authoring mode;
  • In Properties Panel:
    • value of target properties: like ScaleTransform.ScaleX is set to 2;

Blend: Animation Authoring

Blend uses XXXAnimationUsingKeyFrames and generates one keyframe for each object/property/keyframe trio. We can fine tune the properties of a keyframe itself by first selecting it in the Objects Panel, and then setting its properties in the properties panel, like in below screenshot:

  • KeyTime is "00:00:01"
  • target object is button, target path is roughly RenderTransform.ScaleTransform.ScaleX
  • Value is "2"
  • KeySpline is "0.5,0.1,0.5,0.9"

Blend: Animation Authoring

we can also fine tune the properties of the storyboard in the same way, like in below screenshot:

  • Storyboard1 is selected
  • AutoReverse and RepeatBehavior properties are changed

Blend: Animation Authoring

This is the XAML code Blend generated for above simple animation:

  1: <Storyboard AutoReverse="True" RepeatBehavior="Forever" x:Name="Storyboard1">
  2: 	<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="button" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
  3: 		<SplineDoubleKeyFrame KeySpline="0.495999991893768,0.104000002145767,0.5,0.898999989032745" KeyTime="00:00:01" Value="2"/>
  4: 	</DoubleAnimationUsingKeyFrames>
  5: 	<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="button" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
  6: 		<SplineDoubleKeyFrame KeyTime="00:00:01" Value="2"/>
  7: 	</DoubleAnimationUsingKeyFrames>
  8: </Storyboard>
  9: 

Clearly it is much easier to author animations in Blend instead of writing XAML manually.

Template Authoring

The beauty and power of WPF/Silverlight is the capability to re-template a control. It is rather easy to do that in Blend: select an menu item from the "Edit Control Parts (Template) -> Edit Template" context menu, either from Objects and Timeline Panel, or from the breadcrumb in Artboard:

Blend: Template Authoring

"Edit a Copy..." menu item is also an easy way to get the default template of a control. In below screenshot, we can see:

  • default template components in Objects and Timeline Panel
  • visual state groups, visual states, and transitions in Interaction Panel
  • properties of template components in Properties Panel. The orange square to the right of Background property indicates it is template bound.

Blend: Template Authoring

Drill in further: select the Disabled visual state, and we can see that the disabled visual in artboard is generated by the visual state transition storyboard that animates the Opacity property of the DisabledVisualElement from 0% to 55% in 0 second:

Blend: Template Authoring

Please note that near the top of the Object and Timeline panel, it shows Disabled State instead of a storyboard, indicating Blend is in state recording mode.

Now let's make some change to the default template by changing the focus visual state transition to skew the button when it is focused:

Template Authoring

  • select the Focused visual state in Interaction Panel, click the arrow plus icon on its right, select one of the three options (those options are for visual state transitions to and from this state, and between particular two states in the visual state group);
  • Blend is in visual state recording mode: focused is the selected visual state;
  • add a new skew transform to the top grid as discussed in Authoring Animations section. Notice that the button in artboard is now skewed. The WYSIWYG artboard makes animation authoring easy and intuitive.
  • delete the FocusVisualElement template component in Objects panel since we don't need it any more. Notice the tooltip at the top indicating Blend automatically deleted the visual state transition that shows the FocusVisualElement as well.

The Blend generated XAML for above custom template is 102 lines, 6179 characters! Imagine the difficulty in authoring that by hand!

Once we have a template, we can apply it to UI elements of the style's target type (or its sub type):

Apply Template

Style Authoring

Using style is usually better than setting properties on objects directly, since styles can be reused, are easy to maintain, and help separate presentation from content (the UI elements). Style authoring is similar to template authoring discussed above, except it is much simpler. You have to use the Object -> Edit Style menu to enter the style authoring mode. There is no context menu for it, which makes style authoring less discoverable.

Blend: Style Authoring

Select Create Empty... menu item, and the Create Style Resource dialog pops up, allow you to specify the name and location of the new style resource:

Create Style Resource Dialog

Then Blend enters style authoring mode:

  • the Objects and Timeline panel displays highlighted Style element instead of the UI logical tree;
  • the breadcrumb on top of artboard also indicates we are authoring LayoutRoot's style with a palette icon;
  • let's add something to the style by setting Background via the brush editor, notice the artboard reflects the change immediate;
  • the XAML view of documents panel shows the simple XAML generated for style authoring;

Blend: Style Authoring

Once we have a style resource, applying it is easy: just select the object and the use Object -> Edit Style -> Apply Resource menu item.

Apply Style

Resource Management

Storyboard, styles and templates authored above are all resources. We can use the Resources Panel to manage resources:

Resources Panel

  • we can see all the resources in both app.xaml (global resources) and current xaml file page.xaml that is being edited (local resources).
    • Not sure why Storyboard1 created in Animation Authoring section does not show up. Blend bug or user error?
  • we can edit a resource via its context menu or edit resource button:
    Resource Context Menu
  • we can also drag and drop a resource along the tree to change its location (and visibility), like moving between app.xaml and page.xaml, or [UserControl] and button.

Conclusion

To recap, Blend makes UI authoring easy and intuitive:

  • toolbox (and asset library) and artboard allows WYSIWYG UI authoring;
  • objects panel helps to organize all the UI elements in the logical tree;
  • properties panel simplifies property setting with editors;

Building on top of the intuitive UI authoring, Blend simplifies animation authoring by introducing the timeline recording mode:

  • Blend always uses XXXAnimationUsingKeyFrames, so a storyboard is always a collection of keyframes;
  • Blend generates keyframes indirectly by letting user set UI element properties at keytimes via its intuitive UI authoring interface;
  • Blend always generates all four transforms like below, to make its keyframe generation uniform for transforms:

<Button.RenderTransform>
    <TransformGroup>
        <ScaleTransform/>
        <SkewTransform/>
        <RotateTransform/>
        <TranslateTransform/>
    </TransformGroup>
</Button.RenderTransform>

On top of its UI and animation authoring, Blend simplifies template authoring by introducing the template authoring mode and state recording mode. A template consists of template parts and visual states. Template parts are just a logical tree of UI elements, and visual state transitions are storyboards.

Style authoring is even simpler: a style is just a collection of property setters. Blend introduces style authoring mode to distinguish between regular UI authoring and style authoring.

So Blend is a great XAML authoring tool. It is not just for designers, but can also give developers big productivity boost. Hopefully this post gives you a good overview of Blend and get you started in exploring Blend, enthusiastically :-). Thanks!