Sunday, June 6, 2010

A Chrome and Glass Theme - Part 7

This is part 7 of an ongoing series on building a Silverlight theme for use in Blend 3 (I'll move it over to Blend 4 when it's no longer a Release Candidate). The first post in the theme can be found here. If you haven't done much styling of controls before then I recommend you start there since it introduces practices to keep your styles manageable.

This far in the series, I'm focusing on specific parts of the more complex controls.

In this post, we are branching out into the Silverlight Toolkit to style the Accordian control; here it is in the finished Chrome and Glass style:

You can grab the source here.

There are three control templates that we need to customize for this control: the main Accordian template, the AccordianItem template, and the AccordianButton template. You can probably guess that this control inherits from ItemsControl, hence the AccordianItem template which is the ItemContainerStyle from the ItemsControl.

Blend does not play nicely with this control and it can be a little awkward changing styles. I recommend you create the template resources inside the MainPage.xaml while you edit them and then when you are finished, move them into the resource dictionary. This will help, but you will still need to frequently run the Silverlight app to see what your changes look like.

The Accordian Control Template
As you can see, the main control template is fairly simple; basically just a ScrollViewer and an ItemsPresenter.

After creating the "AccordianChromeStyle" resource, I had to reset the margins to 0, the width and height to Auto, and the horizontal and vertical alignment to Stretch. I've then set the BorderBrush on the template style to the "ChromeBorder" resource brush, and set the Foreground brush to white.

Back inside the template, I've set the CornerRadius on the Border control to 5, to stay consistent with the rest of our theme. I've also added a margin of 2 to all edges of the ScrollViewer control to give a little space around the edges of the items in accordian.

The Accordian Item Control Template
It pays to create some dummy (or actual) AccordianItem elements before styling this template. You can add these by right clicking the Accordian control and selecting the "Add AccordianItem" menu. Then add some controls inside the Accordian Items.

I called the "Generated Item Container" resource the "AccordianItemChromeStyle" - this template too is fairly simple. The two elements of importance are the ExpanderButton and ExpanderSite elements; their names making obvious their functions.

You may have some trouble here getting the Accordian to behave properly inside Blend - it doesn't always expand correctly to show you the active accordian item.

On the AccordianItemChromeStyle style resource I have set the Background and BorderBrush both to "No brush". Inside the template I've removed the template-bound Background brush from the top level Grid element and instead put it on the "Background" Border element. I did this because I've also set the corner radius on the Border element to 8 (the default was 1), and the Grid doesn't support rounded corners. This means that if I decide to give the template a background color (instead of "No brush") then there won't be any square corners poking out around the rounded border.

You can ignore the ExpanderButton and ExpandSite elements. The ExpandSite element doesn't need to be customized (it's essentially just a content control), and the ExpanderButton custom template should be customized from the main control, rather than the AccordianItem template.

The Accordian Button Control Template
The Expander button is the workhorse of the Accordian control (at least, visually) and has the largest template. The template to the left shows an extra Border element called "Darkening" that I added to the default template - other than that, the layout is the same.

On the style resource itself, I've set the Background to the "ChromeGlassFill" resource brush. Inside the template I've set the "ExpandedBackground" Border element's Background brush to the ChromeFill resource brush, and the "Darkening" Border element's Background to the "ChromeDarkeningLinear" resource to provide a little more contrast behind the white foreground text of the button. The "Darkening" element has its Opacity set to 0% since it will only be made visible in the "Expanded" state. I've also set the CornerRadius of those two Border elements, and the "MouseOverBackground" Border element, to 3. The "MouseOverBackground" also has it's Background brush set to the "ChromeDarkeningLinear" resource.

The only other changes to the default template are the "arrow" shape has its Stroke changed to black, and the "header" element has it's Vertical Alignment set to Stretch and it's top and bottom margins set to 6 and 0 respectively.

The AccordianButton template has quite a few State groups. I have ignored the ExpandDirectionStates - which causes the headings to expand from one of the four edges - because the ChromeBackground brush doesn't look any good when stretched vertically so I'm not supporting the "Left" and "Right" expand directions in this style, and the "Top" and "Bottom" states work just fine as they are.

The ExpansionStates contains the "Collapsed" and "Expanded" states; the "Expanded" state effectively being the "selected" state. As mentioned earlier, I show the "Darkening" element in this state to provide extra contrast. There is also a "CheckStates" group, since the AccordianButton inherits from the ToggleButton, but these states are ignored by the Accordian.

I've made one or two other small changes to the states, so grab the source and have a dig around inside.