共用方式為


XAML is for tools

There is quite a bit of discussion internally and externally about the role of XAML in WinFX development.  One of the main questions is "Why would I use XAML instead of C# or VB?"

Simply put, "Sparkle", "Cider" and other design tools provide the main justification for the use of XAML.  Previous efforts such as the WinForms designer have shown that using an imperative style programming language as a serialization mechanism is just asking for trouble...especially if the developer hand modifies any of the generated code.  The problem is the tool must reason about the code, basically figure out its intent, and that is hard given a general programming language.  Declarative languages like XML and HTML can be designed to be more regular and less expressive than something like C++ (see syntactic sugar), but as a result easier for the tool to completely undertstand (HTML hasn't been ideal for this either, but I would argue that is largely the legacy of the original irregular nature of the HTML language (mostly fixed by XHTML), and its chaotic evolution by the browser warriors of the late 90s.)

XAML has been designed with tools in mind from the beginning.  In fact, in the beginning there was a strong tension between toolability and hand-editing of XAML, but in the last 12 months this has been generally resolved in favor of toolability (thanks Chuck!).   For example, XAML eschewed a CSS-like syntax for Styles in favor of a completely XML based version because it reduced the number of grammars the parsers and serializers needed to deal with (see syntactic sugar).  More recently there has been a drive to remove the other "mini-languages" from the Avalon specific parts of XAML.  In particular just last week the Avalon team removed the mini-languages for transforms and gradients.  Let me give an example from the Sparkle source code.  The ScaleTab of our TransformPanel has some paths with gradients.  The code for one of these used to look like this:

<Path Canvas.Left="2.239542961" Canvas.Top="3.165508" Fill="LinearGradient 0,0 1,1 #FFFFFFFF #FFA9BCD8" Stroke="#FF185175" StrokeThickness="0.5pt" StrokeMiterLimit="4" Data="M 0 0 L 7.83187484741211 0 L 7.83187484741211 7.59562969207764 L 0 7.59562969207764 Z" />

The blue bits are the declaration of the gradient.  The mini-language is the "LinearGradient 0,0 1,1 #FFFFFFFF #FFA9BCD8" string.  Clearly this isn't XML, so some other parser must be involved.  The XAML parsers and serializers work by determining the type of the property (Fill property, type == Brush) and looking up a TypeConverter for that type.  BrushTypeConverter then knows how to convert strings to and from brushes.  In the simplest cases BrushTypeConverter can handle "#FF0000FF" and "Blue" to represent a SolidColorBrush of the color opaque blue (this is in itself a mini-language, more on that later).  In the more complex case, it parses "LinearGradient 0,0 1,1 #FFFFFFFF #FFA9BCD8" and figures out this is a LinearGradientBrush with a start point of {0,0}, and end point of {1,1} with the two gradient stops of the specified colors. Frankly, neither the transform mini-language nor the gradient mini-language are that complex, but they do represent a bunch of additional work for the various parsers (see syntactic sugar), they need to be supported and updated individually as the object model changes, and they've turned out to be source of more than a few bugs (potentially even security issues if your parser is written unmanaged and vulnerable to buffer overruns). 

Removing the mini-language required me to rewrite this section of Sparkle as so:

    <Path Canvas.Left="2.239542961" Canvas.Top="3.165508" Stroke="#FF185175" StrokeThickness="0.5pt" StrokeMiterLimit="4" Data="M 0 0 L 7.83187484741211 0 L 7.83187484741211 7.59562969207764 L 0 7.59562969207764 Z" >
      <Path.Fill>
           <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
             <LinearGradientBrush.GradientStops>
                   <GradientStopCollection >
                     <GradientStop Offset="0" Color="#FFFFFFFF"/>
                      <GradientStop Offset="1" Color="#FFA9BCD8"/>
                  </GradientStopCollection>
             </LinearGradientBrush.GradientStops>
          </LinearGradientBrush>
        </Path.Fill>
  </Path>   

There was considerable angst about this change internally.  These particular mini-languages are not terribly hard for the tools to learn, they make the XAML smaller and easier to hand-edit, and finally the mini-language rule is not completely consistent.  Being able to represent a Brush with "#FF0000FF" or "Blue" is still a mini-language, albeit simpler.  And more damning, my example above still contains the Path.Data mini-language, which we decided not to remove (largely because it bloats the XAML files). 

I think we made the right choice.  Partly this is self-interest on my part as a tool author.  But further, I argue that neither the transform nor the gradient mini-languages were much use.  A real gradient or transform is so complex you can't really visualize it in your head just from reading the code, regardless of whether pulled apart into "full-blown" XAML or just a mini-language.

Comments

  • Anonymous
    October 08, 2005
    ...On the other hand, if someone just wanted to specify a simple gradient for something like a button, with no intermediate stops or other complexities, the "mini-language" approach to gradients was ideal (and surely most people have no trouble envisioning the transition from start colour to end colour?).

    Sorry to sound grumpy, but this trend suggests that UI development for even relatively simple WPF applications is looking like SOFI (Sparkle Or Forget It)...so at this point don't blame us for starting to nag now (I was planning to wait a while...) with the logical question "How much is Sparkle going to cost?".
    If it's anything like the prices charged for graphical tools then WPF could be stillborn.
    And that would be a terrible shame.

  • Anonymous
    October 08, 2005
    I'd make the argument the other way. We have made XAML so toolable that if we charge too much for Sparkle or Cider, somebody else can easily write their own tool...

    Seriously, the Sparkle argument never went "we need this so we can build Sparkle", it always went "we need this so anybody can build tools for Avalon".

  • Anonymous
    October 10, 2005
    There's something to be said for consistency, and the selective removal of mini-language support from (seemingly arbitrary) tags doesn't increase consistency.

    Additionally, the removal of mini-languages affects not only the dev who handcrafts XAML but also the developer/designer who enters values in the Sparkle property editor since type converters are used there as well

  • Anonymous
    September 27, 2007
    You've been kicked (a good thing) - Trackback from DotNetKicks.com

  • Anonymous
    September 28, 2007
    PingBack from http://fineartz.info/tales-from-the-smart-client-xaml-is-for-tools/

  • Anonymous
    January 24, 2008
    PingBack from http://softwareinformation.247blogging.info/tales-from-the-smart-client-xaml-is-for-tools/