jump to navigation

Silverlight Viewbox April 30, 2008

Posted by Jose Luis Latorre Millas in Silverlight.
1 comment so far

On the past MVP Summit, on which I assisted as an ASP.Net MVP (curiously my activity last year has been mostly of WPF and Silverlight talks) I commented the need of having the WPF Viewbox control on Silverlight 2.0… Silly of me I didn’t realized that I could do it myself as it’s pretty easy to subclass or define user controls for this new version, fortunately my seat companion and one of the main Spain WPF & Silverlight experts, Miguel Jimenez, told me “Hey, why don’t you make it yourself?” And well, he was absolutely right, so here it is… at least a preliminary version of it that more or less does the work I need done.

I basically inherited from the Canvas panel (first tried from the panel base class, but realized it would be easier through Canvas subclassing). Then I wanted it to scale its contents when its allowed space (width and height) grows up or down. Then I added dynamically a ScaleTransform and a TranslateTransform on it’s constructor, added them to a TransformGroup and added it to the Class RenderTransform property (inherited from Canvas).

//Initialization

this.ST_scale = new ScaleTransform();

this.TF_offset = new TranslateTransform();

//We add a transform with the Scale and Translate Transforms…

TransformGroup tg_transformViewbox = new TransformGroup();

tg_transformViewbox.Children.Add(this.ST_scale);

tg_transformViewbox.Children.Add(this.TF_offset);

//We add this Transform to the ViewBox (Subclassed from the Canvas class)

this.RenderTransform = tg_transformViewbox;

Then the only thing left to it was to implement an override for the ArrangeOverride function (more info here: http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.arrangeoverride(VS.95).aspx ).

There I determine the scale ratio, choosing the minimum ratio from the X and Y calculated ratios. Also I adjust the offset for the Y or X axis, to adjust more properly the positioning.

protected override Size ArrangeOverride(Size finalSize)

{

//We scale the contents based on the desired size width and height.

double scaleX = finalSize.Width / this.DesiredSize.Width;

double scaleY = finalSize.Height / this.DesiredSize.Height;

//By default we only allow an “uniform” Stretch attribute option.. we could add the attribute and held the logic in this function.

// See: http://msdn2.microsoft.com/en-us/library/system.windows.media.stretch.aspx and http://msdn2.microsoft.com/en-us/library/system.windows.controls.viewbox.stretch.aspx

// To do this more seriously, we should also add the StretchDirection and Stretch properties too.

if (scaleX > scaleY)

{

//Lowest scale ratio wins (Y axis is lower)

this.ST_scale.ScaleX = scaleY;

this.ST_scale.ScaleY = scaleY;

this.TF_offset.X = (finalSize.Width – this.DesiredSize.Width * scaleY) / 2;

this.TF_offset.Y = 0;

}

else

{

//Lowest scale ratio wins (X axis is lower)

this.ST_scale.ScaleX = scaleX;

this.ST_scale.ScaleY = scaleX;

this.TF_offset.Y = (finalSize.Height – this.DesiredSize.Height * scaleX) / 2;

this.TF_offset.X = 0;

}

return base.ArrangeOverride(finalSize);

}

And this is all is there to it… I didn’t needed to override the MeasureOverride (check http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.measureoverride(VS.95).aspx). Also if you want to know more about creating custom panels, there are some things to read:

The code has been uploaded here: <<<viewboxzip>>> but has a small problem that I realized afterwards.

As a small notice, this code is licensed under MS-PL (http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx).

This problem is that the “original” WPF Viewbox only allows one control and this one is a Canvas so it allows multiple controls positioned together, so it resizes all accordingly, including the layout, which is respected.

Anyway this is the behavior I wanted to obtain, but it is not the WPF Viewbox behavior, so it’s not Ok… for a WPF Viewbox to do this I should put a Canvas inside the Viewbox and then the controls inside the Canvas.

Hope you have fun with it.  ;)

The link for the source code donwload is here: viewboxzip

Follow

Get every new post delivered to your Inbox.