Tuesday, 18 June 2013

Creating Observables. contd..

Just like creating observables with Observable.Return, we can create an observable stream which actually returns nothing, i.e. it calls OnCompleted() directly:-


Why do we have Observable.Empty() and Observable.return() when we could just return a value or null?

This is to support an existing design where some code expects an observable. For example say, we are mocking something in unit tests and we have to provide an Observable stream. We don't care about the actual data, but for code to compile, an observable is required. There will be many scenarios where these could be used once you start thinking in a reactive manner.


Observable.Range()

This is comparable to Enumerable.Range of the IEnumerable world. This will basically create a range of Observables and will call OnCompleted in the end. So the marble diagram for Observable.Range(10,4) will be:-



Simple isn't it?


Creating Observables from lists and arrays:-

From lists:-

            List<int> mylist = new List<int>{1,2,3,4,5,6};
            var myObseravle = mylist.ToObservable();


From Arrays:-

            int[] myArray = new int[] { 1, 2, 3, 4, 5, 6 };
            var myObseravle = myArray.ToObservable();


We can consume above observables easily by subscribing them. This was easy and was easy to understand and till now you might be wondering if this was of much use. Now lets start creating Observable streams from more complex things - this will be of much use.


Creating observables from Events

There are two methods which can be used for converting events to streams of observables:-
Observable.FromEvent(..)
Observable.FromEventPattern(..)

Both these methods exhibit similar behaviour. The difference as explained by Bart De Smet [MSFT] from microsoft team is:-
"Use FromEvent for events structurally don't look like a .NET event pattern (i.e. not based on sender, event args), and use FromEventPattern for the pattern-based ones. The sample code show for FromEvent above violates this distinction and uses an EventHandler inside (which indicates the use of the pattern)."


Let us write a simple wpf application with a textbox and a textblock. The requirement is that as the user types the text in the textbox, it should get copied into the textblock.




1. Create a new WPF application.
2. Open Mainwindow.xaml and add the following xaml:-

    <StackPanel>
        <TextBox x:Name="txtWord" />
        <TextBlock x:Name="txtBlock" Height="200"/>
    </StackPanel>


3. Add handler for window loaded and copy paste the following code:-

        private void Window_Loaded_1(object sender, RoutedEventArgs e)
        {
            var textChangedEvent = Observable.FromEventPattern(txtWord, "TextChanged");
            textChangedEvent.Subscribe(_ => txtBlock.Text = txtWord.Text);
        }


that's is it. This will be enough to achieve the desired functionality.

Ok, so far so good. Now suddenly there is a new requirement. We need to display the total word count in the title bar while the user is typing.


No problem. Just a matter of another subscription. Add the following line to the cs code and we are all done:-

            textChangedEvent.Subscribe(_ => this.Title = "Word Count= " + txtWord.Text.Split(' ').Count());


This was easy!

But now there is another requirement. Once the word count reaches 10, we don't want more in the textblock. User can still type, but it won't be copied in textblock.

Now we need to know how to unsubscribe! Stay tuned for my next post.

No comments:

Post a Comment