Welcome to MSDN Blogs Sign in | Join | Help

The layout system lies have become a bit more elaborate [LayoutTransform functionality updated and enhanced for Silverlight 2 Beta 2!]

In the introductory post for LayoutTransformControl, I showed a trivial use case to demonstrate the need for LayoutTransform in some scenarios. 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 described how my LayoutTransformControl sample did just that, but implemented only RotateTransform functionality for its initial release. My impression then - as now - is that rotation is easily the most common use of LayoutTransform. However, there are plenty of scenarios where the other Transform subclasses (scale, skew, matrix, etc.) are required, and I wanted to have a solution for them as well.

So I've added full support for arbitrary transformations to LayoutTransformControl along with updating it for Beta 2! (The complete implementation - along with demo and test applications - can be found in LayoutTransformControl.cs in the attached ZIP.)

Where you might previously have written:

<local:LayoutTransformControl Angle="15">
    <TextBlock Text="I am rotated 15 degrees!"/>
</local:LayoutTransformControl>

You now write:

<local:LayoutTransformControl>
    <local:LayoutTransformControl.Transform>
        <RotateTransform Angle="15"/>
    </local:LayoutTransformControl.Transform>
    <TextBlock Text="I am rotated 15 degrees!"/>
</local:LayoutTransformControl>

Wait a second! That's more typing than before - why is this an improvement? Well, because you can also do this (just as you would on WPF):

<local:LayoutTransformControl>
    <local:LayoutTransformControl.Transform>
        <ScaleTransform ScaleX="1.5" ScaleY="2.5"/>
    </local:LayoutTransformControl.Transform>
    <TextBlock Text="I am a little wider and a lot taller!"/>
</local:LayoutTransformControl>

Or this:

<local:LayoutTransformControl>
    <local:LayoutTransformControl.Transform>
        <MatrixTransform Matrix="-1,0,0,1,0,0"/>
    </local:LayoutTransformControl.Transform>
    <TextBlock Text="I am flipped horizontally!"/>
</local:LayoutTransformControl>

Or even this:

<local:LayoutTransformControl>
    <local:LayoutTransformControl.Transform>
        <TransformGroup>
            <ScaleTransform ScaleX="1.5" ScaleY="2.5"/>
            <SkewTransform AngleX="10"/>
            <MatrixTransform Matrix="-1,0,0,1,0,0"/>
            <RotateTransform Angle="15"/>
        </TransformGroup>
    </local:LayoutTransformControl.Transform>
    <TextBlock Text="I am all of the above - and tilted, too!!"/>
</local:LayoutTransformControl>

So maybe it's a bit of an improvement, after all... :)

Naturally, I updated my sample application to show off the new capabilities:

LayoutTransformControl Sample Application

And I updated my cross-platform test suite as well (here's the WPF version):

LayoutTransformControl Test Matrix on WPF

LayoutTransformControl should now be just as powerful as WPF's LayoutTransform is. Your application can take advantage of complete LayoutTransform functionality today - even though the Silverlight platform still doesn't officially support LayoutTransform!

Notes:

  • Improvements to Silverlight in Beta 2 (vs. Beta 1) meant that I was able to remove the lesser of the two Silverlight-specific workarounds present in the Beta 1 code.
  • I removed Button from the test matrix and added two new test cases to cover scenarios where LayoutTransformControl was previously behaving incorrectly. (Unfortunately, the default Button template in Beta 2 still causes the Button to measure/arrange itself incorrectly in some cases. The existing ContentControl test cases already cover correct Button behavior, so there's no loss of coverage.)
  • In WPF, changes to the members of a Transform property (be it an individual Transform or a TransformGroup) automatically cause the Transform property's property changed handler to be invoked (even though OldValue==NewValue). This is a wonderfully elegant way to handle the situation - and unfortunately this behavior isn't present on Silverlight. So LayoutTransformControl needs a way to know when one of its Transform members has been updated and it can't rely on Silverlight to tell it. One solution is to try to create a Binding to the relevant properties of each of the members. Unfortunately, Bindings don't work on Transform-derived classes in Silverlight (my theory: because Transform derives from DependencyObject instead of FrameworkElement where the SetBinding method is implemented). So what I've done is create a set of "Ltc"-prefixed Transform-derived classes that do provide automatic notifications (but still not Binding support - due to the same Silverlight limitation, I suspect). So instead of RotateTransform, you use LtcRotateTransform and get change notifications for free. The "Ltc" Transforms have the same transformation properties (ex: Angle, ScaleX) as their counterparts, so they're simple, plug-compatible replacements - with two caveats: LtcTranslateTransform doesn't exist (because TranslateTransform has no effect during LayoutTransform), and the CenterX/CenterY properties aren't implemented (for the same reason).
  • The "Ltc" Transforms are a pretty good workaround, but you don't have to use them. If the members of the LayoutTransformControl's Transform property never change, then change notification is unnecessary and the standard Transforms can be used without issue. The code in the "Motivation" project (part of the attached solution) demonstrates this approach. If the members of the Transform property do change and you're able to use the "Ltc" transforms, then the right thing should happen automatically. The code in the "Sample" project demonstrates this approach. But if your scenario is such that the members of the Transform property do change and you're unable to use the "Ltc" Transforms, all is not lost! LayoutTransformControl exposes a public TransformUpdated method that you can call to notify it of changes to the members of its Transform property. The code for the test matrix projects uses this last approach.
  • In any kind of project where the goal is to duplicate an existing behavior, it's common to do side-by-side comparisons to find bugs in the new implementation. This is exactly what my WPF test matrix does and it helped me find and fix a number of problems during the development of LayoutTransformControl. However, there typically comes a point at which this comparison process starts revealing differences that turn out to be bugs in the reference implementation. That's usually a pretty good sign that the new implementation is approaching the same level of quality as the old one - and it's a milestone I've hit with LayoutTransformControl. In addition to the "maximal area rectangle" improvement mentioned in the original blog post, LayoutTransformControl exhibits two new, deliberate behavior differences (improvements!) from WPF's LayoutTransform implementation. They're subtle, but they can both be demonstrated in the test matrix. Let me know if you think you've found one! :)
  • The examples above assume the "local" namespace prefix has been mapped to an assembly containing the LayoutTransformControl implementation:

    xmlns:local="clr-namespace:LayoutTransformControlSample;assembly=YourAssemblyName"

My goal with LayoutTransformControl has always been to address a perceived need. It began life as a bit of an experiment, but by now I've become rather fond of the solution and plan to incorporate it into projects of my own. I hope that if you have a need for LayoutTransform behavior in Silverlight, you'll consider LayoutTransformControl, too!

Published Thursday, July 03, 2008 2:00 AM by Delay
Filed under: ,

Attachment(s): LayoutTransformControl.zip

Comments

# Silverlight Cream for July 04, 2008 -- #317

Friday, July 04, 2008 7:37 PM by Community Blogs

Michael Washington on prompting for install, Peter McGrattan updated his Stock List Demo, Joel Neubeck

# re: The layout system lies have become a bit more elaborate [LayoutTransform functionality updated and enhanced for Silverlight 2 Beta 2!]

Thursday, July 10, 2008 3:07 AM by kettch

So, I've got what amounts to a design surface with several different elements that can be moved around and rotated. I use some simple math to make sure that they cannot be drug outside the bounds of the design surface.  I was thinking of using your LayoutTransformControl to make sure that the bounds checking wouldn't get messed up when the controls were rotated.

Can you offer any advice on how the layout control might be used in this way? The controls are already built on a UserControl with a Grid inside to keep the child controls organized. I've tried wrapping the LayoutRoot Grid in the LayoutTransformControl, but it seems to be suppressing my VisualStateManger.GoToState calls that I use to indicate a mouse hover or click. Any thoughts?

Thanks

# re: The layout system lies have become a bit more elaborate [LayoutTransform functionality updated and enhanced for Silverlight 2 Beta 2!]

Thursday, July 10, 2008 1:40 PM by Delay

kettch,

LayoutTransformControl is intended to wrap a single item and give that item the ability to transform as if during the layout pass. As such, I'm not sure wrapping your outer Grid in a LayoutTransformControl would accomplish what I understand your goal to be. What I would expect (without understanding the details of your approach) is that you would wrap the individual elements within the bounds of your layout system in LayoutTransformControl and do their rotations via LayoutTransformControl.Transform/RotateTransform. This should mean that the bounds reported by LayoutTransformControl.RenderSize will accurately reflect the transformation and you (or perhaps the layout system) can then decided if they need to be repositioned further.

Hope this helps!

# re: The layout system lies have become a bit more elaborate [LayoutTransform functionality updated and enhanced for Silverlight 2 Beta 2!]

Thursday, July 10, 2008 3:27 PM by kettch

Ok, I actually had to write a small wrapper to make it easier to manage a collection of LayoutTransformControl's and still be able to access the functionality of the underlying UserControl. However, I think I'm misunderstanding how transforms work. I can't seem to get the transforms to work programatically.

Shouldn't something like the following work?

       Dim rot As New LayoutTransformControlSample.LtcRotateTransform

       rot.Angle = 90

       Dim tg As New TransformGroup

       tg.Children.Add(rot)

       ActiveControl.Transform = tg

# re: The layout system lies have become a bit more elaborate [LayoutTransform functionality updated and enhanced for Silverlight 2 Beta 2!]

Thursday, July 10, 2008 4:01 PM by Delay

kettch,

Yes, I would expect the scenario to work. To check for myself, I created a new test project - and things seem to work properly. Here's the XAML and code for it - when the button is clicked, the new text shows up rotated. Hope this helps!

<UserControl x:Class="LTCinCode.Page"

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

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

   <StackPanel x:Name="LayoutRoot">

       <Button Content="Click me to add some rotated text!" Click="Button_Click"/>

   </StackPanel>

</UserControl>

using System.Windows;

using System.Windows.Controls;

using LayoutTransformControlSample;

namespace LTCinCode

{

   public partial class Page : UserControl

   {

       public Page()

       {

           InitializeComponent();

       }

       private void Button_Click(object sender, RoutedEventArgs e)

       {

           var ltc = new LayoutTransformControl();

           ltc.Transform = new LtcRotateTransform { Angle = 45 };

           ltc.Child = new TextBlock { Text = "Hello world." };

           LayoutRoot.Children.Add(ltc);

       }

   }

}

# re: The layout system lies have become a bit more elaborate [LayoutTransform functionality updated and enhanced for Silverlight 2 Beta 2!]

Thursday, July 10, 2008 6:25 PM by kettch

It turns out that I was making it more complicated than it needed to be, and my wrapper wasn't allowing good enough access to the LayoutTransformControl.

After some further fiddling with it, everything is working great. Thank you very much for your help!

# re: The layout system lies have become a bit more elaborate [LayoutTransform functionality updated and enhanced for Silverlight 2 Beta 2!]

Thursday, September 25, 2008 4:20 PM by NinetiesGuy

Is there a way to have the LayoutTransformControl respect the CenterX and CenterY ScaleTransform properties? In my scenario, I have a large Image control nested in a ScrollViewer. The layout control is the only way I have found for the scroll bars to update based on content scale, but when I use the scale transform (standard or Ltc), the image is always scaled from the top left, ignoring any attempts to set a registration point. The same behavior occurs when using a MatrixTransform (standard or Ltc).

Thanks in advance,

Chris

# re: The layout system lies have become a bit more elaborate [LayoutTransform functionality updated and enhanced for Silverlight 2 Beta 2!]

Thursday, September 25, 2008 5:15 PM by Delay

Chris,

I note in the third bullet point above that it's my understanding that CenterX/CenterY do not have any effect when used with LayoutTransform on WPF (and as I recall, this is backed up by my reading of the code). To demonstrate my point, here's a simple XAML demonstration - I find that changes to the values of CenterX/CenterY seem to have no visual effect:

<Button Content="Button" HorizontalAlignment="Center" VerticalAlignment="Center">

 <Button.LayoutTransform>

   <ScaleTransform ScaleX="5" CenterX="-100" CenterY="100"/>

 </Button.LayoutTransform>

</Button>

If you have a counterexample that you can share, I'd love to come to an understanding here!

# Maintaining pretenses with the layout system [LayoutTransform functionality updated for Silverlight 2!]

Monday, September 29, 2008 4:07 AM by Delay's Blog

In the introductory post for LayoutTransformControl and the feature-enhancing follow-up , I gave a variety

# An unexceptional layout improvement [Two LayoutTransformControl fixes for Silverlight 2!]

Tuesday, November 18, 2008 1:35 PM by Delay's Blog

I'd almost finished patting myself on the back for managing to implement WPF's LayoutTransform on Silverlight

# Having problems with layout? Switch to Plan B! [LayoutTransformControl scenarios for WPF]

Thursday, November 20, 2008 1:52 PM by Delay's Blog

When I first wrote about adding full LayoutTransform fidelity to Silverlight with my LayoutTransformControl

# A rose by any other name... [LayoutTransformControl on track to ship in the Silverlight Toolkit under the name LayoutTransformer!]

Monday, March 02, 2009 3:40 PM by Delay's Blog

I'm a believer in the power of LayoutTransform - so much so that I wrote a control to graft this capability

# A bit more than meets the eye [Easily animate LayoutTransformer with AnimationMediator!]

Thursday, April 09, 2009 4:04 PM by Delay's Blog

I came across a question on the Silverlight Toolkit support forum yesterday asking how to animate the

Anonymous comments are disabled
 
Page view tracker