Following the theme from my previous two posts, this post will be about using Reactive Extensions on Windows Phone 7. I'll use a similar scenario as before – gradually load a few tiles into an ItemsControl. Let’s get started.
Starting a project
Create a new “Windows Phone Application”. Add references to assemblies Microsoft.Phone.Reactive and System.Observable to add support for Rx, then Microsoft.Phone.Controls.Toolkit (found in Silverlight Toolkit for Windows Phone 7) and System.Windows.Interactivity (Expression Blend for Windows Phone 7 SDK, should be already installed if you installed WP7 tools / Expresion Blend 4 SP1).
Layout
Put a ListBox on the main, name it list and possibly change the control to an ItemsControl (we don’t need to select items).
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ItemsControl Name="list" /> </Grid>
Create the ItemTemplate:
<DataTemplate x:Key="TileTemplate"> <Grid Width="142" Height="142" Background="{StaticResource PhoneAccentBrush}" Margin="5"> <TextBlock Text="{Binding}" FontSize="{StaticResource PhoneFontSizeExtraExtraLarge}" Foreground="{StaticResource PhoneForegroundBrush}" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="20,0,0,10" /> </Grid> </DataTemplate>
… use WrapPanel for the ItemsPanel:
<ItemsPanelTemplate x:Key="WrapItemsPanelTemplate"> <toolkit:WrapPanel /> </ItemsPanelTemplate>
… and update the ItemsControl to use them:
<ItemsControl Name="list" ItemTemplate="{StaticResource TileTemplate}" ItemsPanel="{StaticResource WrapItemsPanelTemplate}" />
Reactive Extensions
I copied the code from my previous post:
public partial class MainPage : PhoneApplicationPage { public MainPage() { InitializeComponent(); Loaded += OnLoaded; } private readonly string text = "reactive wp7"; private void OnLoaded(object sender, RoutedEventArgs e) { text.ToObservable() .OnTimeline(TimeSpan.FromSeconds(.3)) .ObserveOnDispatcher() .Subscribe(AddLetter); } private void AddLetter(char letter) { list.Items.Add(letter); }
Animating on appearance
Instead of using layout states as in Silverlight version (they are not supported in WP7’s ListBox), I was back on using a behavior to trigger the entrance animation:
public class LoadedBehavior : Behavior<FrameworkElement> { protected override void OnAttached() { base.OnAttached(); AssociatedObject.Loaded += AssociatedObject_Loaded; } void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e) { CreateStoryboard().Begin(); } private Storyboard CreateStoryboard() { Storyboard sb = new Storyboard(); DoubleAnimation animation = new DoubleAnimation { Duration = TimeSpan.FromMilliseconds(1000), From = -90, To = 0, EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } }; Storyboard.SetTargetProperty(animation, new PropertyPath("(UIElement.Projection).(PlaneProjection.RotationY)")); sb.Children.Add(animation); animation = new DoubleAnimation { Duration = TimeSpan.FromMilliseconds(1000), From = 0, To = 1, EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut } }; Storyboard.SetTargetProperty(animation, new PropertyPath(UIElement.OpacityProperty)); sb.Children.Add(animation); Storyboard.SetTarget(sb, AssociatedObject); return sb; } }
Wrapping up
The last thing to do was adding the behavior to the ItemTemplate and prettify the layout a bit.
That’s it, pretty easy. The demo project can be downloaded from here. In the future I’ll look into using more Reactive Extensions on Windows Phone 7 – stay tuned.