Maintaining pretenses with the layout system [LayoutTransform functionality updated for Silverlight 2!]
In the introductory post for LayoutTransformControl and the feature-enhancing follow-up, I gave a variety of examples to convey the need for LayoutTransform. I also noted that Silverlight 2 supports only RenderTransform, but went on to demonstrate how it was possible to use RenderTransform to get LayoutTransform behavior. I'm biased, but I happen think LayoutTransform is a pretty fundamental part of application design - and the feedback I've gotten about LayoutTransformControl suggests that at least some of you agree with me. :)
Soon after the Silverlight 2 release candidate became available, a customer contacted me to ask about updating LayoutTransformControl. I've spent some time doing just that and am happy to share a version that works well on the latest Silverlight 2 bits. The complete implementation - along with demo and test applications - can be found in
LayoutTransformControl.cs in the ZIP file attached to this post.
The sample application works the same as it did before (with the updated look-and-feel of the new bits):
It remains my belief that LayoutTransformControl for Silverlight 2 is just as powerful as WPF's LayoutTransform. Your application can take advantage of complete LayoutTransform functionality today - even though the Silverlight platform doesn't support LayoutTransform!
- Unfortunately, Silverlight does not yet behave the same as WPF with regard to automatically calling the property changed handler of a Transform-typed DependencyProperty when any of that Transform's members change. I explain how clean this makes things in my previous post, and outline how I worked around the issue by introducing a set of custom "Ltc" transforms that automatically notify their LayoutTransformControl parent of any changes. But with the release of the Silverlight 2 RC, the Transform class can no longer be derived from - which forces the removal of the "Ltc" Transforms and completely invalidates my workaround. :(
- There are now just two scenarios for the Transforms provided to a LayoutTransformControl:
- The Transforms are static - so change notifications are unnecessary and there's no need to worry about this. (As before, the Motivation project demonstrates this scenario.)
- The Transforms are dynamic and it is now necessary to make a call to
LayoutTransformControl.TransformUpdated()whenever they change so that LayoutTransformControl can find out and update its rendering. (The Sample project has been changed to demonstrate this scenario.)
- Silverlight 2 has introduced a feature known as "layout rounding" - it's conceptually very similar to WPF's SnapsToDevicePixels property. (I can't find documentation of the new
UIElement.UseLayoutRoundingproperty quite yet, but it's discussed briefly in the Breaking Changes document.) Unlike WPF's SnapsToDevicePixels which takes effect silently (as I understand it), Silverlight's UseLayoutRounding (which defaults to
True) does not. Specifically, UseLayoutRounding causes some of the intermediate values used during the measure/arrange pass to change while LayoutTransformControl is busy working its magic. Left alone, these unexpected changes appear to LayoutTransformControl as various special-cases of the layout system and cause incorrect layout for certain special angles/scales/etc. based on whether things get rounded up or down. So LayoutTransformControl disables UseLayoutRounding for itself (which avoids bad layout during scaling) and that automatically inherits to its templated Grid (which avoids bad layout during rotation). Consequently, LayoutTransformControl's rendering behavior remains correct at all times.
- If UseLayoutRounding is necessary for some element within a LayoutTransformControl, simply set it back to
Trueon that element and things should continue to work as desired. But note that LayoutTransformControl does look at the outermost child element (the value of its
.Childproperty) for some of its calculations, so UseLayoutRounding should not be toggled on that element. If necessary, wrap that element in a container (ex: Grid) and it should then be fine to set UseLayoutRounding on it.
My thanks to everyone who has expressed interest in LayoutTransformControl or is actively using it in their projects! I hope this update continues to serve you well as Silverlight 2 approaches final release.