ChrisAn's Blog Please read my disclaimer.

simplegeek

a.k.a. Chris Anderson

Of styles and styling

A great comment from Yves says "Have you not learned anything from CSS, HTML and the future direction of not using inline styles, but using CSS for look and feel(color, font, position ...) outside of the HTML document (or at least in the head)?"...

Avalon has a solid notion of styles. All appearance of an element can be determined from a style. Avalon styles are hierarchical - that is they can be defined at any scope an impacts from that location down in the tree. Avalon styles are not rule based (like CSS) but rather used a "named style" mechanism. Avalon styles support the definition of property and event based transformations (although I believe the event triggers aren't working in the PDC bits). First, lets look at a basic style:

<Window ...>
    <Window.Resources>
        <Style def:Name="MyStyle"><Button Background="Red" /></Style>
    </Window.Resources>
    <Button>Hello</Button>
</Window>

In this example the button *would not* be colored red. The style has a name, and therefore you would need to specify on the button:

<Button Style="{MyStyle}">Hello</Button>

The curly brace syntax means that the style is being set from a resource reference. Resources can be defined and overriden anywhere in the tree. If you have browsed the SDK documentation for Longhorn you have probably seen styles that look like this:

        <Style><Button Background="Red" /></Style>

This is what we call a "default" or "implicit" style. This requires some explanation. You see every element has a default value for every property. The default value for the "Style" property is the type of that element... OK, more explanation needed. The name of a resource can be any object, not just a string. Thus, you can actually make a resource have the name of "*Int(5)" which would be the integer value of 5 (don't try this in the PDC build, doesn't work <G>). However, one thing you can do is use a type reference:

        <Style def:Name="*typeof(Button)"><Button Background="Red" /></Style>

Ahh! So, we can use the type of an element to be the key for that style in the resource collection.

When designing the styling system we had a lot of discussion about how people would discover the default value of the style. We could have used a naming convention like "SysButton" or something else, but in the end the simplicity of using the type object from the CLR was the perfect fit. The final piece of this puzzle is that when you omit the name of style, we assume that you meant to use the type of the element that the style is for. Bingo.

OK, now that we have named the style, and have a way for elements to hook up to the style, how does a style work?

The basis of style is an "as use" syntax, that is - the content of the style should be just like the element when you would use it. This made it easy for cut and paste type operations, but also made a single syntax for people to learn. In addition, there are style specific properties you can set - like "VisualTree" and "VisualTriggers".

Before I dive into the fun of tree & triggers - one more comment about the lookup rules for resources (and therefore styles)... You can define resources at any level of the hierarchy. Including the application object. Thus, if you want to define the look for all buttons in your application you can simply say:

<Application ...>
    <Application.Resources>
        <Style def:Name="MyStyle"><Button Background="Red" /></Style>
    </Application.Resources>
</Application>

Although this is a really long winded response to Yves, I hope he can see that we haven't forgotten styling.

11/01/2003 3:06 PM | #Longhorn

Content © 2003 Chris Anderson | Subscribe to my RSS feed.

Powered by BlogX