Silverlight Layout States with Reactive Extensions

I’ve been working on several applications where I needed to display several items in a ListBox (or an ItemsControl) at startup, but they had to appear on the screen one by one, with a short delay, not all at once. Using ListBoxItem’s layout states took care of handling how an individual item would appear in the list, but I still needed to handle a short pause between each item being added to the list. Usually I resorted to using a Timer, which sorted out that needed delay for me, but that really felt like hacking that had nothing to do with the real problem.

Reactive Extensions, however, offer a much elegant solution. The GenerateFromTime() construction operator is a close relative to the Generate() operator used in my previous blog entry, except GenerateFromTime() adds an important time dimension to generated sequence – the last parameter in this operator lets you specify a delay between each call to OnNext():

private readonly IObservable<string> numbers = Observable.GenerateWithTime(1, i => i <= 8, i => i + 1, i => i.ToString(), i => TimeSpan.FromSeconds(.3));

The above code snippet will produce an observable sequence of 8 strings, progressing through these strings with a 0.3 seconds delay.

The rest of the code:

private void OnLoaded(object sender, RoutedEventArgs e)
{
    numbers.ObserveOnDispatcher().Subscribe(AddImage);
}

private void AddImage(string image)
{
    list.Items.Add(image);
}

Note the ObserveOnDispatcher() operator again – GenerateWithTime uses a timer operating on a background thread so we need to ensure the AddImage() method is called on the UI thread.

Layout states for this sample are kept really basic:

<VisualStateGroup x:Name="LayoutStates">
    <VisualStateGroup.Transitions>
        <VisualTransition GeneratedDuration="0:0:1">
            <VisualTransition.GeneratedEasingFunction>
                <CubicEase EasingMode="EaseOut"/>
            </VisualTransition.GeneratedEasingFunction>
        </VisualTransition>
    </VisualStateGroup.Transitions>
    <VisualState x:Name="AfterLoaded"/>
    <VisualState x:Name="BeforeLoaded">
        <Storyboard>
            <DoubleAnimation Duration="0" To="-94" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)" Storyboard.TargetName="grid" d:IsOptimized="True"/>
            <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid" d:IsOptimized="True"/>
        </Storyboard>
    </VisualState>
    <VisualState x:Name="BeforeUnloaded"/>
</VisualStateGroup>

And the final result can be observed by following this link.image

This post has shown how to use Reactive Extensions in Silverlight to gradually fill a ListBox, with a bonus of a nice item entry animation, provided by the layout states.

Download source code from here.



tweetmeme_url = 'http://tozon.info/blog/post/2010/10/05/Silverlight-Layout-States-with-Reactive-Extensions.aspx'; tweetmeme_source = 'andrejt';
Avtor: Anonymous, objavljeno na portalu SloDug.si (Arhiv)

Leave a comment

Please note that we won't show your email to others, or use it for sending unwanted emails. We will only use it to render your Gravatar image and to validate you as a real person.