Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

Reactive.buffering.from event.

Reactive?

This post is continuing the series about Reactive Extensions, a powerful little framework currently available for .NET 3.5 & 4, Silverlight 3/4, Windows Phone 7 and JavaScript,  that Microsoft’s Dev Labs are working on.

Buffering?

In this post, I’ll look into two reactive operators that will help me shape my Windows Phone 7 app into something that could eventually be called a  game, even. Those operators are:

BufferWithTime. BufferWithTime() will buffer values, produced in a specified time interval, to publish them all at once when that interval ends. Take, for example, a logger service, where you don’t need to log all events at once; instead, you would check your log queue every minute or so and log all queued events in a batch.

BufferWithCount. BufferWithCount() does a similar thing, but instead of a Timespan value, it takes an integer that specifies the number of values to buffer, before publishing all buffered values.

From event?

We know the FromEvent() construction operator already – it-s used to observe the sequence of specified events, the observation starting upon subscribing to that sequence.

So?

Right… Ok, let’s take the code from the previous post and build on that. Where I left it off was having an ItemsControl with nine tiles in it. What I wanted to do next was make those tiles react to user mouse clicks…

So let’s go and do that, taking small steps.

The source code for this blog post is available from here.

To be able to subscribe to tiles’ mouse events, we first need to find the visual elements representing them. This may seem a difficult task at first, because ItemsControl’s Items property holds a collection of data items (in this case, those are letters), not their visual representations. It’s not, really. Actually, this is a Linq query that will project the collection of letters (data) to a collection of tiles (visuals) through the item container:

IEnumerable<DependencyObject> c = from i in list.Items
                                  select list.ItemContainerGenerator.ContainerFromItem(i);

We’re going to observe these tiles so we’ll turn them to an observable collection:

IObservable<DependencyObject> oc = c.ToObservable();

Now, here’s the trick. We’re going to use a single Linq expression that will notify the observer whenever a tile (any tile!) has been clicked with a mouse, handing it a reference to that tile:

IObservable<Control> ee = from i in oc
    from e in Observable.FromEvent<MouseButtonEventArgs>(i, "MouseLeftButtonDown")
    select VisualTreeHelper.GetParent(((Grid)e.EventArgs.OriginalSource).Parent) as Control;

The expression is three part:

  1. Take all tiles and
  2. subscribe to their MouseLeftButtonDown event and
  3. when that event happens, return a reference to the tile that raised that event (using VisualTreeHelper to get tile’s parent element, as for the item's data template shown below).

Subscribing to this observable sequence of tiles will enable us to react to tile MouseLeftButtonDown events:

ee.Subscribe(Reveal);

In reaction to the mouse down event, we’ll make the tile go into a “Selected” state:

private static void Reveal(Control control)
{
    VisualStateManager.GoToState(control, "Selected", true);
}

But for this, we need to adjust the tile’s data template first. This is a simple “two-sided element” template that flips slides when going between Selected and Unselected sides. Visual states are used to represent the state on each of the side and transitions between those states. I also added the third state – the Matched state will make the matched tiles disappear:

<DataTemplate x:Key="TileTemplate">
    <ContentControl>
        <ContentControl.Template>
            <ControlTemplate>
                <Grid x:Name="TileRoot"
                      RenderTransformOrigin="0.5,0.5"
                      Opacity="0"
                      Width="142"
                      Height="142"
                      Margin="5">
                    <Grid.Projection>
                        <PlaneProjection CenterOfRotationX="0" 
                                         RotationY="-90" />
                    </Grid.Projection>
                    <Grid.RenderTransform>
                        <ScaleTransform />
                    </Grid.RenderTransform>
                    <i:Interaction.Behaviors>
                        <ib:LoadedBehavior />
                    </i:Interaction.Behaviors>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="SelectionStates">
                            <VisualState x:Name="Unselected">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"
                                                                   Storyboard.TargetName="front">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="180" />
                                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0" />
                                    </DoubleAnimationUsingKeyFrames>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"
                                                                   Storyboard.TargetName="back">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="180" />
                                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0" />
                                    </DoubleAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.ZIndex)"
                                                                   Storyboard.TargetName="back">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <System:Int32>1</System:Int32>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                                            <DiscreteObjectKeyFrame.Value>
                                                <System:Int32>0</System:Int32>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                        <DiscreteObjectKeyFrame KeyTime="0:0:1">
                                            <DiscreteObjectKeyFrame.Value>
                                                <System:Int32>0</System:Int32>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Selected">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"
                                                                   Storyboard.TargetName="front">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="180" />
                                    </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)"
                                                                   Storyboard.TargetName="back">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="180" />
                                    </DoubleAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.ZIndex)"
                                                                   Storyboard.TargetName="back">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <System:Int32>0</System:Int32>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0.5">
                                            <DiscreteObjectKeyFrame.Value>
                                                <System:Int32>1</System:Int32>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                        <DiscreteObjectKeyFrame KeyTime="0:0:1">
                                            <DiscreteObjectKeyFrame.Value>
                                                <System:Int32>1</System:Int32>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Matched">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="UIElement.Opacity"
                                                                   Storyboard.TargetName="TileRoot">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="1" />
                                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0" />
                                    </DoubleAnimationUsingKeyFrames>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="UIElement.Opacity"
                                                                   Storyboard.TargetName="front">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                                    </DoubleAnimationUsingKeyFrames>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
                                                                   Storyboard.TargetName="TileRoot">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="1" />
                                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1.5" />
                                    </DoubleAnimationUsingKeyFrames>
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
                                                                   Storyboard.TargetName="TileRoot">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="1" />
                                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="1.5" />
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid x:Name="back"
                          HorizontalAlignment="Left"
                          Height="142"
                          Margin="0"
                          VerticalAlignment="Bottom"
                          Width="142"
                          Background="{StaticResource PhoneForegroundBrush}">
                        <Grid.Projection>
                            <PlaneProjection RotationY="180" />
                        </Grid.Projection>
                        <TextBlock Text="{Binding}"
                                   FontSize="{StaticResource PhoneFontSizeExtraExtraLarge}"
                                   Foreground="{StaticResource PhoneAccentBrush}"
                                   VerticalAlignment="Bottom"
                                   HorizontalAlignment="Left"
                                   IsHitTestVisible="False"
                                   Margin="20,0,0,10" />
                    </Grid>
                    <Grid x:Name="front"
                          HorizontalAlignment="Left"
                          Margin="0"
                          VerticalAlignment="Bottom"
                          Background="{StaticResource PhoneAccentBrush}"
                          Width="142"
                          Height="142">
                        <Grid.Projection>
                            <PlaneProjection />
                        </Grid.Projection>
                        <TextBlock Text="{Binding}"
                                   FontSize="{StaticResource PhoneFontSizeExtraExtraLarge}"
                                   Foreground="{StaticResource PhoneForegroundBrush}"
                                   VerticalAlignment="Bottom"
                                   IsHitTestVisible="False"
                                   HorizontalAlignment="Left"
                                   Margin="20,0,0,10" />
                    </Grid>
                </Grid>
            </ControlTemplate>
        </ContentControl.Template>
    </ContentControl>
</DataTemplate>

The game

Great, now we’ve got ourselves a very simple game of revealing tiles. Sounds familiar? Yes, it looks a lot like a Memory  game.

In a Memory game, we’re dealing with pairs, right? Selecting two of the tiles makes up for a single turn in the game. If we take the existing observable collection and  additionally make it buffer to two elements, the observer will only going get notified when the user selects two tiles. But we also need to let the revealing animation to finish (lasts 1 second), so we have to delay the event publication for one second.

var ff = ee.BufferWithCount(2).Delay(TimeSpan.FromSeconds(1));

The OnNext handler will get both data items associated with the tiles, we just need to subscribe:

ff.ObserveOnDispatcher().Subscribe(OnPairRevealed);

The handler’s implementation at this point is this:

private void OnPairRevealed(IList<Control> tiles)
{
    string state = (char) tiles[0].DataContext == (char) tiles[1].DataContext ? "Matched" : "Unselected";
    VisualStateManager.GoToState(tiles[0], state, true);
    VisualStateManager.GoToState(tiles[1], state, true);
}

Matched and Unselected states are the only valid states to transition from the Selected state. Target state is determined by comparing letters on the tiles – if both letters are the same, it’s a match!

Making it work

There’s a tiny small thing left to make this all work. The previous version of this app was showing the initial tile animation only, and now we need to wire in the logic described in this post. Nothing easier – with existing animation sequence subscription, we only need to call the function when the initial sequence ends. So this:

.Subscribe(AddLetter);

becomes this:

.Subscribe(AddLetter, ObserveClicks);

Video and source code

See the application in action…

… and download source code.

Finishing

Reactive Extensions sure are a fun way to program – take a quick run through the source code to see how little code was required to get things moving as shown in the video.

In future posts I’ll shape up this app into more functional Memory game. Possibly end up wanting publishing it on the marketplace…

Oh, and Happy New Year everybody!



My “What’s new in Silverlight 4 demo” app

What’s new in Silverlight 4? Isn’t Silverlight 4, like, old news by now?

Well yes, as the matter of fact, this is one of those long overdue posts that have a hard time getting out. As I’ve been showing these demos since Silverlight 4 Beta came out, this is really the high time I release the source code… Especially when we’re looking to get a fresh preview of Silverlight 5 in the near future.

So here it is – the source code of my Silverlight 4 sample project.

You can also see the project live.

And the rundown of what you can expect to see in the demos:

Fluid layout : Layout states

The first thing you’ll notice when running the demo app is a few images finding it’s way on the screen from the left, sequentially, one by one, with a nice animation. This was done by using new layout states, found on the ListBoxItem. The new LayoutStates (BeforeLoaded, AfterLoaded, BeforeUnloaded) can be used to add a story to your ListBox items. With common ListBox, the effect of items just mysteriously appearing in the box can be confusing to the user, and the same goes for them suddenly disappearing from it. By using animation, you can tell the story of where they came from and why, as well as to where they go when they are removed. Or you just want to prettify your UI a bit. Whatever… Anyway, looking at the code for this reveals nothing really special – the items are simply added to the list:

MenuItems = new ObservableCollection<MenuItem>();

menuItems.Add(new MenuItem { Caption = "WB", ImageUri = new Uri("Assets/html.png", UriKind.Relative), DataContext = "WebBrowser" });
foreach (var videoDevice in CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices())
{
    menuItems.Add(new MenuItem { Caption = videoDevice.FriendlyName, ImageUri = new Uri("Assets/video.png", UriKind.Relative), DataContext = videoDevice });
}
menuItems.Add(new MenuItem { Caption = "RTB", ImageUri = new Uri("Assets/rtb.png", UriKind.Relative), DataContext = "RichTextBox" });
menuItems.Add(new MenuItem { Caption = "Paste", ImageUri = new Uri("Assets/paste.png", UriKind.Relative), DataContext = "Paste" });
menuItems.Add(new MenuItem { Caption = "CLS", ImageUri = new Uri("Assets/clear.png", UriKind.Relative), DataContext = "" });

Nothing special, but there are a couple of tricks: first, to make items appearing one by one, I’ve used a timer:

DispatcherTimer startTimer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(0.2)};
int menuItemCount = 0;
startTimer.Tick += (s, e) =>
                       {
                           MenuItems.Add(menuItems[menuItemCount]);
                           menuItemCount++;
                           if (menuItemCount >= menuItems.Count)
                           {
                               startTimer.Stop();
                           }
                       };
startTimer.Start();

There is actually a better way of doing this now – Reactive Extensions, which I blogged about a couple of posts ago.

Second, I’ve used the BeforeLoaded and AfterLoaded layout states for animating the ItemsControlItems to transition from “non-existing” state to “loaded-and-visible" state. In other words, make them appear on their place in the ItemsControl through animation.

Third – what’s an ItemsControlItem? Out of the box, LayoutStates are only set on the ListBoxItem, if you want to use them on a plain ItemsControl, which also serves as a base for the ListBox, you have to create some kind of workaround, which includes a new class for your item container – ItemsControlItem. See the code for the example.

TextBlock Text trimming

In the menu which appears on the left when you start the app, you may or may not see the text in one on more boxes trimmed. This is achieved with a new property called TextTrimming. Set it to WordEllipsis to enable the trimming:

image

WebCam support and VideoBrush

In the menu code above you might’ve noticed the CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices() enumeration loop – that’s how you enumerate your video-capable devices. Have many webcams plugged in? They’ll all show up in your menu – with the same icon and their name, probably truncated (see above). Hover your mouse over it to reveal their full name in the tooltip.

Clicking the video icon will get you a box with live preview of video stream of the selected cam. The box is an ordinary Rectangle with its Fill property set to VideoBrush, pointing to the selected video device capture source.

Only one VideoBrush can consume a single capture source, but several visual elements can share the VideoBrush. Click on the same video icon again to get another icon with the same video feed.

If you’ve got more than one, you can click on additional video icons to get video feeds from your other cams.

Oh, and running inside browser, you’ll see a nice security dialog, asking you to confirm you’re ok with that cam go live.

MouseWheel support

With video box out on the canvas, hover your mouse over it and play with your mouse wheel – the box will shrink and expand. This is achieved through the MouseWheel event, which many of the Silverlight 4 controls have. Some of them already have their own implementation of the event, generally they don’t.

In this case, a created a MouseWheelBehavior that can be applied to an element to make it work (on a Canvas). You would probably have to adapt it to use it properly; for the sake of this app, it works ok.

The interesting thing here is that if you have a multi-touch monitor, you can try a pinch zoom gesture on the box and it should shrink/expand as well => nice to see Windows APIs being used in Silverlight.

By the way, in this demo, you can drag’n’drop items on the canvas around…

WebBrowser and WebBrowserBrush

WebBrowser in Silverlight is funny… Running the app inside browser and clicking the WB icon will get you a simple box with the “HTML is enabled only in Out-of-Browser mode.” text inside. Run the app outside the browser (installed) and you’ll see a ‘proper’ web page:

image

The links demonstrate different aspects of browser features. Note: the last link will work only when application is installed with elevated trust (set as default with the accompanying sample code).

Adding another “browser” by clicking on the WB icon for the second time will actually bring up a rectangle, filled with the WebBrowserBrush. WebBrowserBrush mimics the referenced WebBrowser appearance at the time it was called on. Because it’s a snapshot it doesn’t react on WebBrowser changes, but you can update it the WebBrowser’s current state by calling the Redraw () method on it.

Right Mouse Click

UIElements in Silverlight 4 support right button clicks in applications, which can be conveniently used to implement a context menu. In fact, Silverlight Toolkit has an implementation of this already ready to use. This application shows how simple it is to implement. Right-click on any of the added elements to change its shape.

RichTextBox Control

A few fresh controls were introduced with Silverlight 4, RichTextBox is one of them. The app shows the simplest demo of it.

NotificationWindow

When clicking a RTB (RichTextBox) icon, a notification window will be displayed on the bottom right corner – another new control. Works outside of the browser only.

Silverlight app as a drop target

Go to your pictures folder and drag some pictures onto the app canvas – they will be shown inside the application – shows integration with the “outside world” / your app can accept files drag’n’dropped into it.

Copy/Paste

Copy text or Xaml and paste it into the app – a text element or a drawing will appear on the canvas. I usually demo this with the Expression Design – draw a shape, choose some colors for stroke and fill, than copy its Xaml (select the shape, then press Ctrl+Shit+C / Copy XAML) and paste into the app. The Xaml will deserialize into a nice Silverlight shape.

Data binding enhancements

Silverlight 4 also extends the data binding with some new properties. In sample code, you’ll notice a couple of running time labels displayed in the bottom right corner of the screen – those will display how the new properties work: the StringFormat property will let you specify the string format right there in Xaml, the TargetNullValue property value will be displayed when the source property value is null, and the FallBackValue will be displayed when there’s an error with the binding itself.

Commanding

Buttons in Silverlight 4 can be assigned objects, implementing an ICommand interface, allowing for implementing separation pattern, well known from Silverlight’s older brother WPF. There are a few commands you’ll find in the sample project – FullScreenCommand, PrintCommand and DelegateCommand, the latter being mostly known for its use in MVVM pattern implementations.

Full Screen pinning

One of the best new Silverlight 4 features is definitely the ability to ‘pin’ the application to a non-primary monitor, which is especially handy for video players. To enable it, you just have to set the FullScreenOptions:

Application.Current.Host.Content.FullScreenOptions = isFullScreenWhenUnfocused ? FullScreenOptions.StaysFullScreenWhenUnfocused : FullScreenOptions.None;

Check the FullScreenCommand in source code for the implementation.

Printing

Basic printing was introduced with Silverlight 4 – you can construct individual printing pages and send them to the printer as bitmaps – enough for simple(r) scenarios, but much better things are on their way in Silverlight 5. PrintCommand shows the simplest possible implementation for printing a page visual.

Other

There are some other Silverlight 4 features you’ll find in the sample code and I won’t be discussing here. Like MEF (Managed Extensibility Framework) or COM interop. And .NET RIA Services, but I don’t know how well they’ll play since the project is dependent on an older version.

Feel free to explore the source code. Just note – it’s demo code so don’t expect much on a best practices side…



Slides: Application Development for Windows Phone 7

I had the pleasure of participating in the local Microsoft roadshow that was going on in the past month.

4 talks. 4 cities. 1 subject: Application Development for Windows Phone 7.

I said I’d publish the slides. Here.

Also, from last I’ve heard, the situation for WP7 developers in Slovenia is improving. More details soon.



Reactive Extensions #3: Windows Phone 7

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 – tiled letters are now gradually filling up the space on the main page, each letter appearing on the screen with a subtle animation. For more details on how that works check out my previous posts on Reactive Extensions.

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.

image



Lost in time? Zip it!

In my last blog post I wrote about using Reactive Extensions together with layout states in Silverlight to gradually introduce collections of data to a ListBoxes. One small problem with code from that post is that I’m generating the sequence of data myself, whereas in real-world scenario would be pulling it from some data source like database or web service. It’s easy to turn an existing collection to an Observable by using the ToObservable() operator, but the generated sequence wouldn’t be time-based, as it would have been if we had used the GenerateWithTime() constructor.

So how do we turn an existing enumerable collection into a time-based observable sequence?

First, we need to convert the enumerable to a plain observable. Here’s the example of such conversion:

private readonly string text = "REACTIVE";

IObservable<char> letters = text.ToObservable();

[Reminder: a string is a collection/sequence of chars – turning this collection into an observable sequence results in IObservable<char>]

Next, we need to create an observable sequence that will serve as a “beat” – a time-based sequence that would define points in time at which we want to “release” (or trigger) the next item in our data collection. The following code will create a fast “beat”, “thumping” at every 300 ms:

IObservable<long> beat = Observable.Interval(TimeSpan.FromSeconds(.3));

Now we only need to lay the numbers from the enumerable collection over created beat and for that, there is a convenient combinator operator available in Reactive Extensions. It’s called – Zip.

IObservable<string> dancingLetters = numbers.Zip(beat, (letter, time) => letter);

Zip operator will take two observable sequences (letters and beat) and produce a new value pair when a new value is present in both sequences, kind of like a zipper. In our case, the letters sequence starts with 8 values and beat starts with zero. As the beat sequence starts producing new values (one every 0.3 seconds), these new values are paired (zipped) with values from letters, resulting in a new pair of data (letter, time) releasing every 0.3 seconds. As we’re only interested in numbers from the numbers sequence, we return only those values, ignoring values values from the beat sequence (=> letter).

dancingLetters is now a time-based observable sequence which we can subscribe to:

dancingLetters.ObserveOnDispatcher().Subscribe(AddLetter);

… and get the same result as in previous post, only with letters.

One great thing about Reactive Extensions is they are very extensible, meaning you can write your own operators by creating new extension methods. For frequent operations like the one we’ve just performed, it’s a perfect fit. Here’s an example of an OnTimeline() operator that would put an observable sequence on a live timeline:

public static class ObservableEx
{
    public static IObservable<TSource> OnTimeline<TSource>(this IObservable<TSource> source, TimeSpan period)
    {
        return source.Zip(Observable.Interval(period), (d, t) => d);
    }
}

With the new operator handy and in place, we could rewrite the previous snippet as (full code ahead):

private readonly string text = "REACTIVE";

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);
}

This application in action can be observed through this link

image

In this post, I extended the code sample from previous post by creating a new extension method that puts an existing observable sequence on a timeline, with delayed item notification.

Download source code from here.



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.



Reactive Extensions – from pull to push: where’s the block?

I’ve discussed Reactive Extensions with a few people after my Rx talk last week and thought I’d clear up some confusion by clarifying on this blog…

One thing to know about Reactive Extensions is that simply going from pull model (enumerating) to push model (observing) doesn’t give you immediate background thread processing – everything is still happening on the same thread.

For example, let’s look at the following code and put a few debugger breakpoints in it:

image

Right at the top, there’s an array of image names I’m adding to the ListBox (AddImage() method). In this WPF app, the OnLoaded() method handles the Loaded event, where foreach loop iterates through the array and calls the AddImage() method.

Red balls indicate the places where I’d put the breakpoints, and the number in it tells the order in which they would be hit. Following the track, it is obvious that the OnLoaded() method is blocking until all images in the array is added into the ListBox.

To transform this code to use the observer/pull model, the following changes are made:

  1. The array (now an IObservable<string>) is generated with the Generate() Observable constructor.
  2. foreach loop is removed from the OnLoaded() method and replaced with the Observable subscription, providing the methods for OnNext and OnCompleted.

The Subscribe() method looks harmless sitting alone on now shortened OnLoaded() method, but guess what – it’s still blocking it! Take a look at the execution path: the code would enter the method, and upon subscription, starts calling the AddImage() method. After that, it calls OnCompleted() and then, only then, continues the execution in the OnLoaded() method and finally exits.

The thing to be careful about here is the fact that even if the images.Subscribe() method looks innocent and instant, it may be executing a long(er) time, if an observable sequence is very long. Which also means that the current thread will be blocked for that time also. And we don’t want the UI thread blocked.

image

What we can do to achieve the behavior we want and expected (not blocking the UI) is forcing subscription on a new – background – thread and expect the observable to call us back on the UI thread. Note that the AddImage() method has to be called on the UI thread because the code accesses the ListBox and if called from a non-UI thread, the call would fail. The code below exercises these changes and results in a whole different flow: upon subscription, the UI thread exits the OnLoaded() method immediately, while the subscription processing is done in a new thread. ObserveOnDispatcher() operator ensures that for each element in the observable sequence, AddImage() method is safely called on the UI thread.

image



Reactive Extensions – from pull to push: where’s the block?

I’ve discussed Reactive Extensions with a few people after my Rx talk last week and thought I’d clear up some confusion by clarifying on this blog…

One thing to know about Reactive Extensions is that simply going from pull model (enumerating) to push model (observing) doesn’t give you immediate background thread processing – everything is still happening on the same thread.

For example, let’s look at the following code and put a few debugger breakpoints in it:

image

Right at the top, there’s an array of image names I’m adding to the ListBox (AddImage() method). In this WPF app, the OnLoaded() method handles the Loaded event, where foreach loop iterates through the array and calls the AddImage() method.

Red balls indicate the places where I’d put the breakpoints, and the number in it tells the order in which they would be hit. Following the track, it is obvious that the OnLoaded() method is blocking until all images in the array is added into the ListBox.

To transform this code to use the observer/pull model, the following changes are made:

  1. The array (now an IObservable<string>) is generated with the Generate() Observable constructor.
  2. foreach loop is removed from the OnLoaded() method and replaced with the Observable subscription, providing the methods for OnNext and OnCompleted.

The Subscribe() method looks harmless sitting alone on now shortened OnLoaded() method, but guess what – it’s still blocking it! Take a look at the execution path: the code would enter the method, and upon subscription, starts calling the AddImage() method. After that, it calls OnCompleted() and then, only then, continues the execution in the OnLoaded() method and finally exits.

The thing to be careful about here is the fact that even if the images.Subscribe() method looks innocent and instant, it may be executing a long(er) time, if an observable sequence is very long. Which also means that the current thread will be blocked for that time also. And we don’t want the UI thread blocked.

image

What we can do to achieve the behavior we want and expected (not blocking the UI) is forcing subscription on a new – background – thread and expect the observable to call us back on the UI thread. Note that the AddImage() method has to be called on the UI thread because the code accesses the ListBox and if called from a non-UI thread, the call would fail. The code below exercises these changes and results in a whole different flow: upon subscription, the UI thread exits the OnLoaded() method immediately, while the subscription processing is done in a new thread. ObserveOnDispatcher() operator ensures that for each element in the observable sequence, AddImage() method is safely called on the UI thread.

image



What's Wrong with *my* WCF Service?

While I was watching the Silverlight TV episode on common WCF service issues with Silverlight (Silverlight TV 46: What's Wrong with my WCF Service?) I remembered one more issue that bit my neck a while back and thought it was worth pointing it out again... It was one of those “Service returned ‘Not found’” issues, except nothing I would do seemed to help solving it.

My simple WCF service was returning an IEnumerable<T> and I was using a Linq query for filtering the results before returning them to the client. Can you guess where I’m going to?

Let’s step back and take a look at the symptoms I was facing: the original problem was that service call returned with the infamous “NotFound” exception.

I would try using Client Http Stack to get more info about the exception – nothing. Reverted to Browser Http Stack and implemented service stack to return Faults – still nothing. I wrapped my service method call into a try…catch statement inside service method – no errors would’ve been caught on the server side and the NotFound error would persist… Furthermore, stepping through the service code didn’t throw any exceptions and the error only happened when service call returned one or more records. When there was zero, it returned fine… Hmmm… Something happening on the wire? Fiddler wasn’t much of a help either.

What helped at last was a careful examination of the service method call. Facepalm! I was failing in materializing the Linq query by not forcing its evaluation with the .ToList() extension method (or similar) and data never made it to the other side.

Lesson learned – when your services return IEnumerable and you’re using Linq to query/transform data double check that you’re returning something that client would actually have a chance enumerating.



Watch Silverlight TV videos, pinned to full screen

One of the “annoyances” with Silverlight (and similar browser plugins) is with watching a video in a multi-monitor set up – you would pop out your Silverlight video player to full screen on one monitor and continue working on your other monitor – which would cause your video player to return to its normal size, ruining your watching experience. Well, that was the case until Silverlight 4 came out. Silverlight 4 supports “full-screen pinning” in a way that you can choose the Silverlight 4 app to remain pinned to full screen on one monitor even if you focus your work on the other.

Unfortunately, (the regular) Channel 9 still doesn’t use Silverlight 4 which means you don’t get this option of full-screen pinning, but guess what – Channel 9 is in a process of refurbishing and a preview of the new site is available at the http://preview.channel9.msdn.com. This is good news for us because they’re using Silverlight 4 for their player, which basically means you can watch your Silverlight TV full-screen pinned simply by prefixing Silverlight TV show’s URL with the word preview. For example, show 40: You Are Already a Windows Phone Developer is available on http://preview.channel9.msdn.com/shows/SilverlightTV/Silverlight-TV-40-You-Are-Already-a-Windows-Phone-Developer/.

However, there seems to be a lag with publishing new content, resulting in shows not being available on the preview site at the same time as on the regular time. At the time of this writing, it appears that Show 40 is the last one available on the preview site, with shows 41 and 42 remaining on the regular site only. Anyway, it’s good to see Channel 9 going Silverlight 4 – hope to the new site up and running soon.