Silverlight 4: New parser implementation. New parser features.

29 March 2010

XamlNewFeatures

Designers wear black turtlenecks. Photo by Lara604 - http://www.flickr.com/photos/lara604/2369412952/ (creative commons) XAML is such an important thing for enabling modern user interfaces that it’s easy to forget how complex and integral the parser is to the Silverlight platform.

It’s the thing that lets us geek out in code when we need to, yet still talk to our designer friends who wear black turtlenecks, dream in Adobe Illustrator actions, and love Expression Blend.

Your designer friends are going to like Silverlight 4 more than Silverlight 3, thanks to new features like direct content.

Developers are going to like Silverlight 4 more, since there are new, better error messages both while using Visual Studio, and at runtime. This means fewer AG_E_UNKNOWN errors.

What’s new?

In Silverlight 4, more than a year of development went into a modern, improved parser to offer new XAML features, fix some common requests and complaints, and develop a modern platform for future parser improvements to build upon.

A number of expert engineers at Microsoft came together to make this possible, and hopefully you’ll find the improvements worthwhile.

In no particular order, and not necessarily exhaustive, here’s a look at some of the changes (more comprehensive information in David Poll’s similar blog post).

Whitespace treatment

XAML in Silverlight 4 is parsed as you’d expect for XML in general: newlines, for instance, don’t show up unless you add the xml:space=’preserve’ attribute first.

<StackPanel Orientation="Horizontal">
    <TextBlock>
       <TextBlock.Text>
          This is the first line of the text block, 
          and this is still the first line.
       </TextBlock.Text>
    </TextBlock>
    <TextBlock xml:space="preserve">
       <TextBlock.Text>
          This is the first line of the text block, 
          and this is the second line.
       </TextBlock.Text>
    </TextBlock>
</TextBlock>

Upgrade warning: This change is double-edged. When we moved the Silverlight Toolkit samples to use the new parser, we were bit by the source code that displays in the source viewer: it was all one line! The preservation line had to be added, since previously we depended on the parser just grabbing and using the newlines from the parser input for breaks in the text boxes.

Direct content

Buttons work better now. You couldn’t do this before:

<Button>Ok</Button>

Error messages

Many, many bugs around error message handling have been fixed thanks to the new parser’s error service implementation. In most situations, errors are more descriptive, similar to their WPF counterparts, and will contain useful line and column number information.

In Silverlight 3, many times XAML parsing problems resulted in errors being identified as being at line 0, column 0, and those days are mostly over.

Dictionaries done right

If a type or property implements IDictionary, you can now use x:Key to add entries into dictionaries. Note that we’re talking about the non-generic IDictionary interface.

ISupportInitialize

A feature WPF developers have enjoyed, begin and end initialization calls are made before and after properties are defined in XAML.

Template bindings require CLR getters and setters

Dependency properties must have defined CLR getters and settings to be used in template bindings, consistent with WPF.

XmlnsDefinitionAttribute

Especially when using the Silverlight Toolkit and other control libraries, you needed to define a new XMLNS definition in every page, for every assembly you wanted to use.

xmlns:controlsToolkit=”…”, xmlns:navigation=”…”, etc.

Now with XmlnsDefinitionAttribute (an assembly-level attribute) support, you often can get by with less. All the assemblies in a single product can share a namespace which you can then just define one time.

x:Uid support

Uids are better supported, paving the way for localization tools and other uses of x:Uid.

Root default namespace restriction removed

Prior to Silverlight 4, the root XAML namespace had to be one of the supported standard namespaces. This restriction is removed. Note that you still need it if you want to reference set properties that come from the core Silverlight elements.

What about backward compatibility?

Compatibility with previous versions of Silverlight is one of the most important goals for the development and test teams working on Silverlight. As a result, there are a fair number of “quirks mode” checks throughout the codebase.

Whenever a bug fix or new feature is implemented, a quirks mode check often needs to be inserted to maintain the previous codepaths for compatibility reasons.

It’s a good technical challenge, and though “quirking” probably has a bad reputation from the Internet Explorer 5 & 6 days, it really does work well in Silverlight.

Dual parser implementations

Beyond just quirks mode checks in the Silverlight runtime, we have decided to also include the Silverlight 3 parser inside of Silverlight 4 for compatibility reasons.

At the start of the code path that parses XAML and eventually returns an object or tree, there’s an if/else check that keeps the parser versions completely separate:

    if (CQuirksMode::ShouldUseSL3Parser(pCore))
    {
        // ... Old parser code path
    }
    else
    {
        // ... New, awesome parser code path
    }

And the underlying quirks mode check whether the application’s major version is less than 4.

Which parser will be used?

The target application’s Silverlight runtime version is what determines which parser will be used at runtime. This value gets placed inside of the application manifest XAML file, in the application’s .Xap, at build time.

If you examine a .Xap file (rename to .Zip, extract the contents), inside the root directory you will find a file named AppManifest.xaml.

In the Deployment element there is an attribute called RuntimeVersion. This needs to start with 4.0 to use the new parser, such as:

<Deployment 
    xmlns="http://schemas.microsoft.com/client/2007/deployment" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    EntryPointAssembly="SilverBugger" 
    EntryPointType="JeffWilcox.SilverBugger.App" 
    RuntimeVersion="4.0.50303.0" />

Note that I’ve removed the rest of the file contents for brevity.

This means that control and component developers need to be aware of this for new controls: if you have a control whose default styles and templates expect the Silverlight 4 XAML parser to be used (if you’re using direct Button content, for example), then you need to make sure your customers only use those components with Silverlight 4 applications.

What about System.Xaml?

System.Xaml shipped with WPF 4, and is a modern managed XAML parser implementation. We had signifcant knowledge and code sharing on the team to make sure that the implementations were similar, common, and yet they are different.

The parser in Silverlight is a complex implementation because it often has to bridge the native/managed code gap: so much of the core Silverlight runtime is implemented in native code, so properties and other information need to be shared between the two.

Though this is not a technical discussion of the implementation, I will note that there is a crisp interface shared by both a XamlNativeRuntime and XamlManagedRuntime, and it’s pretty impressive.

Let me know how your experiences are with the new Silverlight 4 parser.

Jeff Wilcox is a Software Engineer at Microsoft in the Open Source Programs Office (OSPO), helping Microsoft engineers use, contribute to and release open source at scale.

comments powered by Disqus