1.2 just went live. I fixed the RotateTransition bug and learned a few things in the process. I thought I'd share them with you (these are also included in the issue resolution notes).
Previously whenever a clone (VisualBrush) was made for a Visual the original Visual was hidden. This makes sense in a lot of cases like RotateTransition where the original visuals need to be hidden
while the cube is rotating (the cube shows two rectangles that use VisualBrush to represent the respective original visuals). But you may want to create a transition where the original visual actually stays around (think reflection or water effects).
So I changed the code to not to hide the original automatically and updated all of the transitions that used VisualBrush to hide their original visual when it made sense.
"So what went wrong?" Well, I left a little detail out in my explanation above. When I was making changes and bug fixes to deal with the previous VisualBrush problem I noticed that the visuals
were being placed into an adorner. I didn't understand the reason for the adorner at the time and Adorner isn't available in Silverlight (we eventually want to port if we can). So I removed the Adorner and started dealing with the content directly. And when
I said above that the original Visual was "hidden", that's not exactly the case. The Visual itself can't be set to Visbility.Hidden or the VisualBrush won't render it. Removing the Visual from the Visual Tree won't work either because of the framework
bug that will cause the VisualBrush to crash. So instead of hiding the visual or removing it from the visual tree, I instead
move the visual to a Grid that's in the visual tree but is hidden.
This works in theory, but I had set the grid to Visibility.Collapsed instead of Visibility.Hidden. "Why does that matter?" It matters because Visibility.Collapsed means that layout will never
occur for the items inside the grid. "And why does that matter?" It matters because if a Visual is never added to a container that performs layout, a VisualBrush pointing at that visual won't have anything to render.
"So why did it effect only RotateTransition?" Well, it turns out that RotateTransition is the
only transition currently that uses VisualBrush to represent both the old content and the new content. The old content renders just fine because it's already been visible on the screen. But the new content has never had
it's layout performed and we're just shuffling it off to the hidden grid (which also doesn't do layout). So the new content doesn't get rendered until after the transition completes and it gets put into the regular Child collection.
"Okay, that explains why it didn't work from A to B, but why did it work from B to C"? That's because I left out one final detail. TransitionElement internally uses ContentPresenters to host
the old content and the new content. This is so we can support data templates. In truth, it's actually the content presenters that needed to have their layout run. After we'd completed at least one transition, both presenters had their layout run and from
that point onward everything works as expected.
"Alright, but how'd you fix it?" Glad you asked. As usual, for such a complicated problem the fix was pretty simple: I changed the hidden grid from Visibility.Collapsed to Visibility.Hidden.
That way anything in the hidden container will still participate in layout and this approach has two benefits: The first is that our VisualBrush will have content to render. The second is a side effect but it's a great one. Since the hidden grid expands to
fill TransitionElement, whenever TransitionElement resizes the hidden content and their associated Visual Brushes will update accordingly. I don't know if you noticed the "squishing" or "stretching" that used to happen with RotateTransition
when the content wasn't in the visual tree, but that doesn't happen anymore.