While working on one of my WP7 applications I noticed a weirs problem. The app is pretty simple with just two pages. I added the same page load animation, see below, to both pages and all seemed to work just fine.
<phone:PhoneApplicationPage.Projection>
<PlaneProjection
x:Name="plane"
CenterOfRotationX="0"/>
</phone:PhoneApplicationPage.Projection>
<phone:PhoneApplicationPage.Triggers>
<EventTrigger>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="plane"
Storyboard.TargetProperty="RotationY"
From="-90"
To="0"
Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</phone:PhoneApplicationPage.Triggers>
The animation cause the page to rotate in and is something I copied from Charles Petzold eBook Programming Windows Phone 7 although I shortened the time to just half a second. While developing everything worked just fine when I ran mu application in the emulator. However when I deployed my application to a real phone I noticed that the first page ran the animation just fine but the second page didn’t show the animation at all.
The hunt for the missing animation
After some trial and error I noticed that the animation started showing up if I increased the time to around 1.5 seconds. And it wasn’t the complete animation, only the last part would show up. The first second or so would just not show up at all. Of course I could have changed the animation to do nothing for a second and then sweep in but that felt like a wrong hack so I decided to find out what was really going on and why the two pages where behaving differently.
The guilty party is data binding
It turned out the main difference between the two pages was the fact that the second used data binding while the first didn’t. And when I removed the DataContext from the second page the animation would show up just as it was supposed to. Of course the data binding was there for a good reason and removing it wasn’t an option so I had to change the way the data binding was initialized.
I was using the excellent MVVM Light Toolkit written by Laurent Bugnion and it uses the ViewModelLocator pattern to hook up the View and the ViewModel. This works really well as Blend understand the paradigm and makes it very easy to do the UI work in Blend. However it also means that the DataContext is set when the page is first created. Normally not a bad thing nu in this case it meant that all data bindings where being evaluated right when the page was created, at the same time as the animation was running. So the solution was to move the runtime data binding to the page Loaded event using the following code:
void SecondPage_Loaded(object sender, RoutedEventArgs e)
{
DataContext = ViewModelLocator.SecondStatic;
}
Of course I also needed to prevent the page from setting the DataContext when first created while still maintaining the blendability of the page. This is achieved by making a small change to the ViewModelLocator class in the property that returns the ViewModel when the page is loaded%u00b1
public SecondViewModel Second
{
get
{
if (SecondStatic.IsInDesignMode)
return SecondStatic;
else
return null;
}
}
With these small changes in place the animation ran just fine and the data binding worked just fine as well.
Conclusion
The two tings I learned from this is not to trust the emulator as it runs a lot faster that the actual Windows Phone 7 and will hide these kind of problems and to set the page DataContext in the loaded events instead of during the page construction.
Enjoy!
www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu