Page view counter

Silverlight Toolkit: ViewBox

Hi Folks,

 

I’d like for us to take some time and talk about the new Silverlight Toolkit Viewbox control.

We’ll deep dive on what Viewbox does, how it does it and the few nooks and crannies it has.

 

Setup

1. Create a new project.

image2_thumb

 

2. Add a reference to the Silverlight Controls assembly (Microsoft.Windows.Controls.dll) which can be downloaded at http://codeplex.com/Silverlight.

image10_thumb   image_thumb3

 

3. Look under "Custom Controls" In the Blend Asset Library.

image13_thumb

 

4. Add a ViewBox to the Page.

image

 

And here's the XAML we got:

<UserControl

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    mc:Ignorable="d"

    x:Class="SilverlightControlsNovember2008.ViewBoxPage"

    Width="640" Height="480" xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls" xmlns:SilverlightControlsNovember2008="clr-namespace:SilverlightControlsNovember2008">

    <Grid x:Name="LayoutRoot" Background="#FFFFFFFF">

        <controls:Viewbox Height="100" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100"/>

    </Grid>

</UserControl>

 

 

 

Introducing Dobby The Penguin

ViewBox is meant to resize SIlverlight XAML to fit the available screen realestate.

As such, it’s optimal to be used in 2D graphics and less relevant for ordinary controls.

We’ll demo ViewBox with some 2D content. However, my drawing talent is limited to that of a 3yr old.
So, with the gracious approval of Jose Fajardo we’ll be using one of his XAML drawings – Dobby the penguin. 

image

Dobby enjoys snow-boarding, long walks on the beach, and is 320x300 pixels big. (approx. Width x Height)

 image

Dobby has a pretty complex XAML file (which you can find here). In order to reuse Dobby without copy-pasting his XAML all over the place, we’ll create Custom Penguin control.

I’ve pasted the XAML into Blend, and now we’ll “right click –> Make Control” on the penguin canvas.

image

We’ll call our now control “PenguinControl”.

image

 

And here’s the XAML behind our Penguin Control:(you can copy the full XAML from here)

<UserControl

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    mc:Ignorable="d"

    x:Class="SilverlightControlsNovember2008.PenguinControl" Width="323" Height="301"

    >

 

    <Grid x:Name="LayoutRoot">

        <Canvas Height="301" x:Name="Penguin" Margin="0,0,317,179" Width="323"> 

            … <!-- Full Xaml Here -->

        </Canvas>

    </Grid>

</UserControl>

 

 

ViewBox with Fill Stretch

We’ve mentioned that ViewBox resizes it’s content based on it’s own size. In order to test that theory we’ll create 3 ViewBoxes:

1. The First (100,100) pixels

2. The second (250,250) pixels.

3. The Third (400,400) pixels.

image

We’ll also set our Viewboxes to use Stretch to Fill.

image

Next, we’ll put Each ViewBox in a Border that has a BorderBrush off Black and a BorderThickness of 1.

image

We’ll click on BorderBrush and than “Solid Color Brush”.

image --> image

And we’ll set BorderThickness to 1.

image

And here’s our ViewBoxes

 image

 

Here’s the XAML blend generated for us up until now:

<UserControl

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    mc:Ignorable="d"

    x:Class="SilverlightControlsNovember2008.ViewBoxPage"

    Width="800" Height="480" xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls" xmlns:SilverlightControlsNovember2008="clr-namespace:SilverlightControlsNovember2008">

 

    <Grid x:Name="LayoutRoot" Background="#FFFFFFFF">

        <Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" VerticalAlignment="Top">

            <controls:Viewbox Height="100" Width="100" Stretch="Fill" />

        </Border>

        <Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" Margin="120,0,0,0" VerticalAlignment="Top" >

            <controls:Viewbox Height="200" Width="200" Stretch="Fill" />

        </Border>

        <Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" Margin="340,0,60,80">

            <controls:Viewbox Height="400" Width="400"Stretch="Fill" />

        </Border>

    </Grid>

</UserControl>

 

 

Now let’s place Dobby the Penguin into each of our Viewboxes.

image

And we can see Dobby has been resized to Fill the ViewBox.

Stretch.Fill tells the ViewBox –" “make sure this content takes up the entire width & height of the Viewbox”.  

 

 

ViewBox with Uniform Stretch

Fill Stretch makes sure the element fills up both Height & Width.

The only way to scale up an item to fill those both is to distort the ratio between Height & Width.

image

As you can see in this exciting table, Dobby’s fill ratio is equal to that of the viewbox – 1.
However, Dobby’s original ration was 1.07. That means that making Dobby scale to fill distorts him.

If we set the Viewbox Stretch to Uniform we’ll get the same ratio though.

image 

 

And this is how Dobby likes like now:

image

 

Let me crank up mspaint and highlight the new whitespaces in our Viewboxes.

image

We can see that Dobby is now filling all the Width of all the Viewboxes, but not all height.

The reason is that the Viewbox is smart enough how to scale up/down the controls in it without distorting them or changing their ratio.

 

Here’s the XAML Blend generated for us:

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" VerticalAlignment="Top">

    <controls:Viewbox Height="100" Width="100" Stretch="Uniform">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" Margin="120,0,0,0" VerticalAlignment="Top" >

    <controls:Viewbox Height="200" Width="200" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="Uniform">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" Margin="340,0,60,80">

    <controls:Viewbox Height="400" Width="400" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="Uniform">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

 

 

ViewBox with Uniform Stretch, HortizontalAlignment and VerticalAlignment

As we’ve seen a Viewbox with Stretch to Uniform might have some Whitespace left on the Top & Bottom or the Left & Right.

By default, Viewbox places the control in HorizontalAlignment and VerticalAlignment of Center.

We’ll select our Uniform Viewboxes and  set their VerticalAlignment to Top.

image

Let’s see how Dobby looks like now:

image

We can see Dobby still has the same amount of Vertical Whitespace, But now Dobby is aligned to the Top and the Whitespace is all at the Bottom.

 

Here’s the XAML we created here:

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" VerticalAlignment="Top">

    <controls:Viewbox Height="100" Width="100" Stretch="Uniform" VerticalAlignment="Top">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" Margin="120,0,0,0" VerticalAlignment="Top" >

    <controls:Viewbox Height="200" Width="200" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="Uniform" VerticalAlignment="Top">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" Margin="340,0,60,80">

    <controls:Viewbox Height="400" Width="400" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="Uniform" VerticalAlignment="Top">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

 

Similarly if we set VerticalAlignment to Bottom, the opposite of what we’ve just seen would be true.

image

Here’s how Dobby looks like now:

image

And we can see that Dobby is aligned to the Bottom and the Whitespace is on the Top.

 

Here’s the XAML blend generated for us:

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" VerticalAlignment="Top">

    <controls:Viewbox Height="100" Width="100" Stretch="Uniform" VerticalAlignment="Bottom">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" Margin="120,0,0,0" VerticalAlignment="Top" >

    <controls:Viewbox Height="200" Width="200" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="Uniform" VerticalAlignment="Bottom">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" Margin="340,0,60,80">

    <controls:Viewbox Height="400" Width="400" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="Uniform" VerticalAlignment="Bottom">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

 

In a very similar fashion, we could have set HorizontalAlignment for placement of Horizontal whitespace.

 

 

 

ViewBox with UniformToFill Stretch

 UniformToFill is very interesting in that it Fills the Viewbox, but in the same time doesn’t change the Height-Width ration of the Control nested in it.

Let’s see that.

image

Here’s our design-surface looks like:

image

We can see that Dobby fills all the space given to it and yet keeps his original Height-Width ratio.

However, Dobby is clipped on the right side to allow that. Similarly Dobby might have been clipped on the bottom if it was necessary.

 

Here’s the XAML Blend generated for us:

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" VerticalAlignment="Top">

    <controls:Viewbox Height="100" Width="100" Stretch="UniformToFill" VerticalAlignment="Bottom" HorizontalAlignment="Stretch">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" Margin="120,0,0,0" VerticalAlignment="Top" >

    <controls:Viewbox Height="200" Width="200" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="UniformToFill" VerticalAlignment="Bottom">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" Margin="340,0,60,80">

    <controls:Viewbox Height="400" Width="400" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="UniformToFill" VerticalAlignment="Bottom">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

 

 

ViewBox with No Stretch

One more option of ViewBox is to just Clip to original content without resizing it.

Let’s have a look at that.

image

Here’s how page looks like:

image

We can see see in the first & second Viewbox that Dobby is clipped based on his top-right corner.

The third Viewbox shows Dobby aligned to the Center in it’s original size.

 

Here’s the XAML Blend generated for us:

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" VerticalAlignment="Top">

    <controls:Viewbox Height="100" Width="100" Stretch="None" HorizontalAlignment="Stretch">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" Margin="120,0,0,0" VerticalAlignment="Top" >

    <controls:Viewbox Height="200" Width="200" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="None">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" Margin="340,0,60,80">

    <controls:Viewbox Height="400" Width="400" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="None">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

 

 

ViewBox with StretchDirection Up & Down

We might sometime want to limit the scaling Viewbox does to only enlarge or shrink the controls in it.

Setting the StretchDirection to UpOnly says the Viewbox can only enlarge controls in it.

Setting the StretchDirection to DownOnly says the Viewbox can only shrink controls in it.

By default StretchDirection is set to Both which states that both Up & Down are acceptable.

 

image

 

Let’s examine how Dobby looks like in each of the 3 Stretch options in each of the StretchDirections.

 

Stretch=Fill, StretchDirection=Both

image

we’ve seen this already, this is standard Fill.

 

Stretch=Fill, StretchDirection=UpOnly

image

Viewbox #1 & Viewbox #2 have not been resized, because they should have scaled down, but we’re only allowed to scale up.
So Viewbox #1 & Viewbox #2 are equivalent to Stretch=None.

Viewbox #3 is still sized to Fill, because it’s been scaled up and that’s allowed.

 

 

Stretch=Fill, StretchDirection=DownOnly

image

Viewbox #1 & Viewbox #2 that need to be scale down their content have done so.

Viewbox #3 that needs to scale up has not done so, and is now equivalent to Stretch=None.

 

Stretch=Uniform, StretchDirection=Both <—Default for viewbox

image

Normal Uniform fill that we’ve previously seen.

 

Stretch=Uniform, StretchDirection=UpOnly

image

Viewbox #1 & Viewbox #2 that needed to be scaled down, have not done so because it’s not allowed. So they’re equivalent to having Stretch=None.

Viewbox #3 has been stretched to uniform with scaling up as expected.

 

Stretch=Uniform, StretchDirection=DownOnly

image

Viewbox #1 & Viewbox #2 that need to scale down in a Uniform Stretch have done so.

Viewbox #3 that needs to scale up has not done so, and is not equivalent of Stretch=None.

 

Stretch=UniformToFill, StretchDirection=Both

image

Normal UniformToFill stretching.

 

 

Stretch=UniformToFill, StretchDirection=DownOnly

image

Viewbox #1 & Viewbox #2 that needs to scale down in a UniformToFill Stretch have done so.

Viewbox #3 that needs to scale up has not done so, and is not equivalent of Stretch=None.

 

Stretch=UniformToFill, StretchDirection=UpOnly

image

Viewbox #1 & Viewbox #2 that needed to be scaled down have not done so because it’s not allowed.
So Viewbox #1 & Viewbox #2 equivalent to having Stretch=None.

Viewbox #3 has been stretched to uniform with scaling up as expected.

 

 

And here’s the XAML Blend generated for us for Stretch=Uniform & StretchDirection=Both: (the defaults)

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" VerticalAlignment="Top">

    <controls:Viewbox Height="100" Width="100" Stretch="Uniform" HorizontalAlignment="Stretch" StretchDirection="Both">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" HorizontalAlignment="Left" Margin="120,0,0,0" VerticalAlignment="Top" >

    <controls:Viewbox Height="200" Width="200" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="Uniform" StretchDirection="Both">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

<Border BorderBrush="#FF000000" BorderThickness="1,1,1,1" Margin="340,0,60,80">

    <controls:Viewbox Height="400" Width="400" BorderBrush="#FF000000" BorderThickness="1,1,1,1" Stretch="Uniform" StretchDirection="Both">

        <SilverlightControlsNovember2008:PenguinControl/>

    </controls:Viewbox>

</Border>

 

 

ViewBox with Button

ViewBox might not be appropriate for all controls, as it’s primary use is 2D vector graphics.

You would probably not have a lot of scenarios to use it in a LOB app.

 

Viewbox essentially does a lot of math for you and sets the appropriate ScaleTransform on the nested Child.

 

Scenario: we have a Button sized 50x50 pixels and we’d like to scale it to 250x250 pixels.

Here’s the original button and it’s XAML:

 image

<Button Height="50" Width="50" Content="Button"/>

 

Option #1: Just change the Height & Width of the button!

image 

<Button Height="250" Width="250" Content="Button"/>

 

Let’s also set an acceptable fontsize for this situation:

 image

<Button Height="250" Width="250" Content="Button" FontSize="48" />

 

 

Option #2: Use a Viewbox

Hey, After all, we’ve just spent time learning about it.

image

<controls:Viewbox Height="250" Width="250">

    <Button Height="50" Width="50" Content="Button"/>

</controls:Viewbox>

 

Looks kinda weird, doesn’t it?

All the lines are very thick and not really subtle, the spacing looks absurd, the color schema which used to look slick now looks overblown.

 

 

Option #3: set a ScaleTransform of times 5

image

<Button Height="50"Width="50" Content="Button" RenderTransformOrigin="0.5,0.5">

    <Button.RenderTransform>

        <TransformGroup>

            <ScaleTransform ScaleX="5" ScaleY="5"/>

            <SkewTransform/>

            <RotateTransform/>

            <TranslateTransform/>

        </TransformGroup>

    </Button.RenderTransform>

</Button>

 

We can see that the result of option #2 and option #3 are completely equivalent.

That’s because, as we said, ViewBox just does a lot of complex math on what ScaleTransform to use.

 

The question of using a ViewBox or not is better articulated by asking “Would I use a Scale trasnform here? or just set Layout properties?”.

 

 

-- Justin Angel

Microsoft Silverlight Program Manager

Published Thursday, November 06, 2008 5:31 PM by JustinAngel
Filed under:

Comments

# Silverlight Cream for November 07, 2008 -- #422

In this issue: David Miles, Shawn Oster, Jeff Weber, Justin Angel, and Nikola Mihaylov. David Anson has

Friday, November 07, 2008 12:42 PM by Community Blogs

# 2008 November 10 - Links for today &laquo; My (almost) Daily Links

Pingback from  2008 November 10 - Links for today &laquo; My (almost) Daily Links

# Silverlight News for November 10, 2008

Pingback from  Silverlight News for November 10, 2008

Monday, November 10, 2008 4:00 AM by Silverlight News for November 10, 2008

# Toolkit posts: &quot;Silverlight in Style,&quot; dependency properties in WPF and Silverlight, and TreeView expansion - Jeff Wilcox

Pingback from  Toolkit posts: &quot;Silverlight in Style,&quot; dependency properties in WPF and Silverlight, and TreeView expansion - Jeff Wilcox

# re: Silverlight Toolkit: ViewBox

Hi Justin,

You have put together a number of very good Silverlight Toolkit tutorials - your efforts are very helpful and very appreciated.

Thank you,

David Roh

JK@SilverlightAzure.com

Monday, November 17, 2008 7:44 AM by davidjjon77

# A Quick Note on XAML Namespaces

Sunday, May 03, 2009 7:55 PM by Frank La Vigne

# A Quick Note on XAML Namespaces in Silverilght/WPF

Sunday, May 03, 2009 7:57 PM by Frank La Vigne

# re: Silverlight Toolkit: ViewBox

Any chance you could update this for the latest drop of the toolkit?  I'm having trouble finding a Silverlight 3 ViewBox tutorial.

Friday, June 12, 2009 4:59 PM by nosuchthingas2