Adventures with the Silverlight Viewbox


When I threw together Twitfeed one of the things I wanted to do was to have the "swatches" scale appropriately so if there were only a few words in a particular tweet it wouldn't look too lost. The Viewbox (currently in preview as part of the Silverlight Toolkit) is perfect for this. The role of the Viewbox is to scale content to fill available space.

For example, below is a simple Silverlight application with a Border containing a TextBlock in the upper cell (Fontsize="24"). In the lower cell, an indentical TextBlock is wrapped in a Viewbox (still inside a Border). On the right is a Listbox that allows you to change the Stretch property of the Viewbox. I've set this to None initially (so no stretch but the Viewbox does have the effect of centering the TextBlock).

If you change the Stretch to Fill, the Viewbox will scale the content without respecting the aspect ratio. Uniform will scale to fill either width or height, respecting the AR and ensuring the content isn't clipped while UniformToFill will scale and allow content to be clipped. There's a good description of the enumeration on MSDN.

Now this all sounds great but I did run into a few obstacles with the Silverlight Viewbox.

Child controls and x:Name

As soon a I put my controls inside a Viewbox I could no longer reference them from code. Actually, all looked well in Visual Studio but at runtime the control (inside the Viewbox) could not be found. Ning Zhang who worked on the Viewbox control has a great post that describes the ins and outs of the control and specifically why x:Name doesn't work for child elements of the Viewbox (FindName doesn't work across namespaces)

Using Viewbox with TextBlocks of variable size with TextWrapping enabled is troublesome

That's an understatement and perhaps this mess was of my own making but trying to get things to size correctly proved nigh on impossible. The trouble is, TextWrapping requires a Width on the TextBlock and my TextBlocks are not of a fixed width. Essentially I just divide the window into a 3x3 matrix of Viewboxes. So each Textbox gets 1/3 of the width. Easy.

However, there seems to be some interaction that occurs with the Viewbox that means the scaling goes to pot (technical term) if you re-size the window then regenerate the TextBoxes. The Window resize is fine but when I refresh the page (essentially refreshing the contents of the Viewboxes) there seems to be some "history" of the original page width that causes the TextBlocks to scale incorrectly (that's my definition of incorrect - ie not the way I'd like :-)).

In the end I have rather a cludgy solution that involves storing the original window size what the app was invoked and modifying the FontSize as the application scales which seems to work okay. I'd prefer a simpler and more elegant solution though.

Using the Viewbox in a Control Template

I wanted to scale the Listbox that represents my list of tweet terms. I could not get this to work (my mistake) but now have it working. I'll post about the tweet terms Listbox separately as there are a few things in there (eg "disabling" selection, highlighting search terms as they change) that I think are worth describing.

The Viewbox is an incredibly handy control but if you find yourself in the arrange / measure / what the heck's going on nightmare that I found myself in, maybe better step back and see if there's a simpler approach to achieve what you want.

Technorati Tags: silverlight,viewbox,twitter