Binary Bob’s Blog

16
Sep

Graphical Skinning Comes to Silverlight

Posted By Bob Bartholomay under Flex Study, Silverlight.

Stuck for time? Go here to see how Peter Blois uses Pixel Shaders to give Silverlight Nine Scale functionality

In the Flex world, there are two ways to “skin” your controls: Programmatic and graphical. The nine yard explaination can be found here but essentially, you either roll up your sleeves and write Actionscript class files that contain drawing API methods or you use raster graphic files as style properties that replace the existing skins of the component. Its a great system and the next version of Flex goes even further as Silverlight style “lookless controls” will be available. See a previous post for details.

The problem: Suppose your designer comes to you and says “We are using this PNG file for the WidgetPanel and by the way, don’t forget that it will be resizable”. Here’s what the file looks like…

Data Sources

The issue you’ll face is that when the Container that this graphic will be used with is resized, the image will resize proportionately and you don’t want that. You only want the inside portion to resize and the border area to remain fixed. This is the concept known as 9Slice or Scale Nine which breaks a rectangular space into 9 “slices” or cells and then resizes the pieces independently when resized.

Flex has Scale9 in the box and its super easy to use. Define a style to use in a CSS file specifying the 4 scale values as follows:

1
2
3
4
5
6
7
8
9
	.containerStyle
	{
		paddingLeft: 23;
		paddingBottom: 30;
		paddingRight: 23;
		border-skin: Embed(source="assets/images/panel.png",
			scaleGridTop="20", scaleGridBottom="60", 
            scaleGridLeft="20", scaleGridRight="150");
	}

Apply the style in the MXML (line 14)…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	layout="absolute" backgroundColor="White">
	<mx:Script>
		<![CDATA[
		private function changeSize():void
          {
             canvas.width= uint(hSlider.value);
             canvas.height= uint(hSlider.value);
          }
		]]>
	</mx:Script>
	<mx:Style source="assets/css/Styles.css" />	
	<mx:VBox styleName="containerStyle">
		<mx:Canvas id="canvas" height="100"/>
		<mx:HSlider width="100" id="hSlider"
			 minimum="10" maximum="500" value="100" change="changeSize();"/>
		<mx:Text text="Adjust Size..." styleName="textStyle"/>
	</mx:VBox>	
</mx:Application>

Here’s the resulting Flex application. Notice how the border is constrained from resizing as you exercise the slider.

That’s pretty slick and very easy and allows Flex designers and coders to coordinate easily and make some really impressive UIs. But don’t despair Silverlighters, we have it in Silverlight now too thanks to Peter Blois (see link at top of page).

Circa Silverlight 2, I tried to use a 3X3 grid with “star sizing” for the middle piece and while it helped, it wasn’t right.

Now with Silverlight 3 and Pixel Shaders (and the brilliance of Peter Blois) we have the same functionality in Silverlight. Here’s a demo:

Here’s the XAML for the Silverlight version showing how simple it is.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<UserControl x:Class="NineScaleDemoSilverlight.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:NineGrid="clr-namespace:NineGrid;assembly=NineGrid"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    <StackPanel x:Name="LayoutRoot">
    	<Grid Name="maingrid" Height="150" Width="150">
            <NineGrid:Scale9 Grid="20,20,20,20">
                <Image Source="panel.png" Stretch="UniformToFill"/>
            </NineGrid:Scale9>
            <Slider Width="100" Minimum="10" Maximum="500" Value="150" ValueChanged="Slider_ValueChanged"/>
        </Grid>
    </StackPanel>
</UserControl>

The beauty of the solution is that Peter has made it easy to use the NineGrid in Blend complete with adorners that you can move around to set the grid.

Adorners in Blend

I’ve been doing back flips since August 7th when Peter posted this but I haven’t seen the Silverlight Community share my enthusiasm. I think that this is a huge feature, but then again I’m easily thrilled. – Cheers!

10 Responses to “Graphical Skinning Comes to Silverlight”

  1. Links (9/17/2009) « Steve Pietrek – Everything SharePoint said:

    [...] Graphical Skinning Comes to Silverlight [...]

  2. Tweets that mention Binary Bob’s Blog » Graphical Skinning Comes to Silverlight -- Topsy.com said:

    [...] This post was mentioned on Twitter by saumya and SilverlightCommunity. SilverlightCommunity said: RT @SilverlightNews: Graphical Skinning Comes to Silverlight – http://snurl.com/ryg9d [...]

  3. Josh Santangelo said:

    I posted this on Peter’s post as well, but I’ll ask here — It’s easy enough to import the DLL to get the Scale 9 effect, but that doesn’t seem to be enough to enable the design-time experience. What does one do with the other DLLs? I’ve tried putting them in Microsoft Expression\Blend 3\Libraries\Silverlight\v3.0\Design but it doesn’t seem to change anything.

  4. Bob Bartholomay said:

    Josh- You do not have to do anything with the other DLLs as they are packaged in the “design” folder by convention and are related to the “design time experience” and are used by Blend. see: Unni’s Blog for an explanation (I could not get the new project template installed though…)

    If your Blend project’s Objects and Timeline looks like this (each a child of its parent):
    [UserControl]
    LayoutRoot
    [Scale9]
    [Grid]
    And the [Scale9] is the currently selected element (highlighted in grey) and you do not see the adorners for the Scale9 control on the artboard, try giving the Scale9 a Width and Height value (not auto) in the layout pane of the Properties palette as it may just not be visible. – HTH

  5. Josh Santangelo said:

    That was the trick. I needed to include the “Design” folder next to the DLL in my project.

    There seems to be a bug with the design experience though. If I zoom in, say 200% and use the adorners, the values set on the grid are 200% of what they should be. You can also see the positions of the adorners move around relative to the object as you zoom in/out.

  6. Edward J. Stembler said:

    In all of my Silverlight apps, I only use vectors and gradients — no raster images.

  7. Binary Bob’s Blog » [screencast] Graphical skinning via NineGrid said:

    [...] last post spoke of Peter Blois’ NineGrid.dll and how it can be used to do Nine Scale in [...]

  8. Bob Bartholomay said:

    Here’s a short video showing its usage in Blend – bob

  9. Silverlight Postings | Codedstyle said:

    [...] Graphical Skinning Comes to Silverlight [...]

  10. Silverlight Postings « Jasper Blog said:

    [...] Graphical Skinning Comes to Silverlight [...]

Leave a Reply