Are you new to Reactive Extensions and looking for a quick tutorial on how to perform a few common tasks in a Windows Store App? In this tutorial you will learn how to throttle TextBox.TextChanged events and use them to search in a collection. You will see how you subscribe to the search results and inform your UI of changes.

Use Reactive Extensions to throttle TextChanged events and subscribe to search results.

Why am I writing about Rx?

Wunderlist

At 6Wunderkinder we make Wunderlist, a multi-platform, multi-user, online/offline, asynchronous application that allows you to organize your life and business.

The multi-user/asynchronous nature of the application presents us with a lot of challenges. We need a local repository (model) that holds the data we need when we create ViewModels that support the Views. But what happens if another user edits data you are looking at right now? A clever sync mechanism changes the model and these changes need to be broadcast to the viewmodels. For this we use Reactive Extensions.

It can be a bit intimidating when you start with RX. So I started with a very simple example that uses Rx to listen to TextChanged events, throttles them and uses them to perform a search. Then, instead of having a function returning a list of search results, the search function returns an IObservable to which the caller can subscribe. The UI looks like this:

ui

How would you do this without Rx?

Rx allows you to do this in 1 stream of data/events. Let’s start with a fake search function to return some data.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;

namespace RxSearch {
public class Api {
public IObservable<List<string> Search(string filter) {
    var list = new List<string> { "Vera", "Chuck", "Dave", "John", "Paul", "Ringo", "George" };
    var filteredList = list.Where(x => x.ToLower().Contains(filter.ToLower()));
    return Observable.Return(filteredList.ToList());
}
}
}

The Search function does not return a List<string> but an IObservable<List<string>. This changes a pull-based result to a push-based result. To return a value, we use Observable.Return(list) which returns an IObservable<List<string> and completes the stream.

<Grid Background="#FF96B209">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox x:Name="textbox" Width="400" Margin="0,0,0,20" FontSize="20"/>
<ListBox x:Name="listbox" Width="400" Height="400" FontSize="20" />
</StackPanel>
</Grid>
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using Windows.UI.Xaml.Controls;

namespace RxSearch {
public sealed partial class MainPage {
public MainPage() {
    InitializeComponent();

    var api = new Api();

    var textchanges = Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
        h => textbox.TextChanged += h,
        h => textbox.TextChanged -= h
        ).Select(x => ((TextBox)x.Sender).Text);

    textchanges
        .Throttle(TimeSpan.FromMilliseconds(300)) // result on threadpool
                .Select(api.Search)
        .Switch()
        .ObserveOnDispatcher() // send back to dispatcher
                .Subscribe(OnSearchResult);

    api.Search("").Subscribe(OnSearchResult);
}

private void OnSearchResult(List<string> list) {
    listbox.ItemsSource = list;
}
}
}

I split the stream into two parts. The event from the TextBox and the data from the Search result.

TextChanges:

var textchanges = Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
        h => textbox.TextChanged += h,
        h => textbox.TextChanged -= h
        ).Select(x => ((TextBox)x.Sender).Text);
**textchanges** is now an `IObservable<string>` that is…well…observable. To observe it, we subscribe to it.

Subscribe to IObservable

Update! In my initial post I used SelectMany to get to the actual data. Then I got this feedback from  the Rx creators themselves.

update

So I tried Select().Switch() and it works beautifully!

textchanges
.Throttle(TimeSpan.FromMilliseconds(300)) // result on threadpool
 .Select(api.Search)
.Switch()
.ObserveOnDispatcher() // send back to dispatcher
 .Subscribe(OnSearchResult);

And that’s really it. OnSearchResult is just a handler to actually fill the ListBox:

private void OnSearchResult(List<string> list) {
listbox.ItemsSource = list;
}

Download the demo project RxSearch

Written by Loek van den Ouweland on 2014-05-08.
Questions regarding this artice? You can send them to the address below.