Showing posts with label Rx. Show all posts
Showing posts with label Rx. Show all posts

Sunday, August 18, 2013

SLAB - Reactive Event Sourcing

In the previous post we saw how we can use ETW events generated using EventSource using PerfView. We can also use these events in our application using EventListener. This is another new abstract type provided in .net framework 4.5. The abstract member is OnEventWritten() method. Additionally, it has a virtual method OnEventSourceCreated(). Below is a custom event listener. Here we are overriding the two members. We are just writing the debug messages when these methods are called. During development, debug messages can be seen in the Visual Studio's Debug Output window.


The listener's OnEventWritten method is called when EventSource writes an event. But before that we need to specify what level of events we are interested in from the EventSource. This is called Enabling the events where listener is specified with the EventSource and EventLevel.

You can notice OnEventSourceCreated and OnEventWritten being used by the logs in the Output window. The above code wold result the following logs:



Semantic Logging Application Block
Semantic Logging Application Block is provided in Enterprise Library 6 for supporting structured logging. It enhances EventSource to support logging events in SQL Server and Azure tables. Like other application blocks, this is also available as a Nuget package.



SLAB provides custom implementation of EventListener. The listener is Rx's IObservable. This is named as ObservableEventListener. Since this implements IObservable, it allows subscriptions from Event sinks. The sinks are IObserver (s) to observe on these event listeners.



The application block also provides a specialization of EventSource. This is named as SemanticLoggingEventSource.



In-Process Vs Out-Process
SLAB can be used in-process or out-process. We can use the Nuget package to use the libraries for using it in process. For out of process, it is hosted as a windows service. The service installer is available as a separate download. In the previous post, we discussed how we can use out-process logging with SLAB.

Event Text Formatter
SLAB supports JSON and XML based text formatting. The types are available in Microsoft.Practices.EnterpriseLibrary.SemanticLogging.Formatters namespace available in Microsoft.Practices.EnterpriseLibrary.SemanticLogging assembly. The assembly is downloaded using EnterpriseLibrary.SemanticLogging nuget package.



Event Sinks & Factories
SLAB also provides Event Sinks and their factories. All of these event sinks are IObserver.



Let's install EnterpriseLibrary.SemanticLogging application block nuget package. The package should take care of all its dependencies installation as well, which is only comprised of Newtonsoft.Json package.



Let's also install Rx-Main nuget package for subscriptions using Reactive extensions based subscribers.



In the following code we are subscribing to ObservableEventListener. We can get the messages in the OnNext() method for the subscriber. Here we have also used OnCompleted() and OnError() of the subscriber.

Running the above code would result in the following output. Please notice that the messages being logged using the event source as provided to the listener. Since we are subscribing to the listener, we are getting those messages in OnNext(). Here we are just writing those messages to Debug Window.


Download

Thursday, February 24, 2011

Rx - Executing anonymous code asynchronously

In the previous post we discuss about how we can execute a method asynchronously using Reactive Extensions. In this post we will discuss how we can execute anonymous code asynchronously using Reactive Extensions. Rx provides this support using Observable.Start.

Invoking Actions (No data returned):
Let us start with discussing how we can execute code asynchronously with no data to return.


The event handler of Click event of the button is as follows:

private void button2_Click(object sender, RoutedEventArgs e)
{
Observable.Start(() =>
{
Thread.Sleep(2000);

return;
}
)
.ObserveOnDispatcher()
.Subscribe(
(result) => { ;},
(ex) => this.Background = Brushes.Red,
() => this.Background = Brushes.Green);
}

This code just executes simple code asynchronously in a ThreadPool thread. It generates OnNext, OnCompleted and OnError messages on the Dispatcher thread as we are observing on Dispatcher. After atleast two seconds the background of window should turn green.

Invoking anonymous code (data returned from lambda) asynchronously:
We can also execute anonymous asynchronous code using Observable.Start which actually return a value. This code is in the form of lambda expressions or lambda statements which explicitly return data through return statement. Let us add a button on the same window. When user clicks the button it should update the operand boxes with any random number.

private void btnFillRandomOperands_Click(object sender, RoutedEventArgs e)
{
Observable.Start<int>(
() =>
{
Thread.Sleep(2000);
return new Random().Next(1, 10);
}).ObserveOnDispatcher<int>()
.Subscribe(
(result) =>
{
this.textBoxOperand1.Text = result.ToString();
this.textBoxOperand2.Text = result.ToString();
},
(ex) => this.Background = Brushes.Red,
() => this.Background = Brushes.Green
);

}

The above code uses Random class to generate a random number between 1 and 10. The returned number is provided to OnNext handler by Rx runtime. This handler updates both operand text boxes with this number. After this, the runtime places OnCompleted handler which turns the background of the window to green.

When we run this and click this button, it results in the following window after atleast 2 seconds. Definitely, it might be a different random number generated and filled in the operands text boxes.



Passing Arguments to Code executed by Observable.Start:
It doesn’t seem that we can have any parameters to Observable.Start directly. But we can use our old technique of using Captured Variables. As we know that lambdas can capture variables from the scope they are generated from. The variables used by lambda like this are called Captured variables. Like a regular lambda statement executed asynchronously, these variables also have Closure issues. I have discussed here how to avoid closure issues by assigning the value of captured variables to local variables inside lambdas.

http://shujaatsiddiqi.blogspot.com/2010/12/wpf-dispatcherbegininvoke-and-closures.html

private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Observable.Start(() =>
{
Thread.Sleep(2000);

return operand1 + operand2;
})
.ObserveOnDispatcher()
.Subscribe(
(result) => { this.textBoxResult.Text = result.ToString(); });

operand1 = 3;
operand2 = 4;
}

In the above case what do you guess would be shown in the result textbox if we enter 2.1 and 3.5 in the two operand text boxes. If you guess 5.6 then you would be surprised to see this result.


This is the result of modified captured variables as the modified value of those captured variables are used which are 3 and 4. The result of addition of 3 and 4 is 7, which is displayed in the Result text box. In order to fix this, we can define two new local variables localOperand1 and localOperand2 and initialize them with the values of captured variables.

private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Observable.Start(() =>
{
decimal localOperand1 = operand1;
decimal localOperand2 = operand2;

Thread.Sleep(2000);

return localOperand1 + localOperand2;
})
.ObserveOnDispatcher()
.Subscribe(
(result) => { this.textBoxResult.Text = result.ToString(); });

Thread.Sleep(2);

operand1 = 3;
operand2 = 4;
}

When we run the application and enter data 2.1 and 3.5 then the correct result is displayed in the Result text box.


Although Resharper still shows warning but it is just fine as we have seen the correct result being calculated.


Observable.Start and Exceptions in the code executed:
As a result of an exception Observable.Start behaves same way as Observable.ToAsync. We can represent the behavior in marble diagram as follows:


Let us update the code executed asynchronously using Observable.Start so that if the sum of number entered is either zero or lesser, it should throw an Exception.

[DebuggerStepThrough]
private void button1_Click(object sender, RoutedEventArgs e)
{
decimal operand1 = Decimal.Parse(this.textBoxOperand1.Text);
decimal operand2 = Decimal.Parse(this.textBoxOperand2.Text);

Observable.Start(() =>
{
decimal localOperand1 = operand1;
decimal localOperand2 = operand2;
decimal sum = localOperand1 + localOperand2;

Thread.Sleep(2000);

if (sum <= 0)
{
throw new System.Exception("Error in computation");
}

return sum;
})
.ObserveOnDispatcher()
.Subscribe(
(result) => { this.textBoxResult.Text = result.ToString(); },
(ex) => this.Background = Brushes.Red,
() => this.Background = Brushes.Green);

}

You can notice that we are still subscribing on Dispatcher. In addition to OnNext, we have provided the code for OnCompleted and OrError. The window should turn green when the operation completed successfully resulting in OnCompleted. In case of exception, OnError is executed.



Using IScheduler to run Asynchronous code:
Like Observable.ToAsync, Observable.Start also provides overloads to run the asynchronous code using different IScheduler. We can run code which returns or does not return any data in the form of lambda and we can run it using the IScheduler of our choice. You can see that just by providing Scheduler.Dispatcher info to Start we can turn this method to run on UI thread:

Observable.Start(() =>
{
Thread.Sleep(2000);

return;
}, Scheduler.Dispatcher
)

Note:
There is one more overload of Observable.Start which returns ListObservable<TSource>. Since it is not about executing anonymous asynchronous code, we are discussing it here.

Download Code:

Thursday, February 17, 2011

IObservable.Throttle causes OnNext on ThreadPool thread

This is a continuation of our following post:

http://shujaatsiddiqi.blogspot.com/2011/02/mvvm-observable-inotifypropertychangedp.html

In the above post we discussed about using PropertyChanged event of INotifyPropertyChanged by observing EventStream support of Reactive Extensions Rx. In this post we change the view model a bit. We remove the implementation of INotifyPropertyChanged. We rather define it as a DependencyObject to support a different change notification mechanism from view model. This is to demonstrate the following:

IObservable.Throttle causes OnNext to be generated on a ThreadPool thread instead.

We will see what problems might be caused by this and how we can work around this.

public class StudentViewModel : DependencyObject
{
#region Model
private Student _model;
#endregion Model

#region Constructor

public StudentViewModel(Student student)
{
_model = student;

Observable.FromEvent<PropertyChangedEventArgs>(_model, "PropertyChanged")
.Where(et => et.EventArgs.PropertyName == "StudentName")
.Subscribe((arg) =>
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
});
}

#endregion Constructor

#region Dependency Properties

public static DependencyProperty StudentIdProperty =
DependencyProperty.Register("StudentId", typeof(int), typeof(StudentViewModel));
public int StudentId
{
get { return (int)GetValue(StudentIdProperty); }
set { SetValue(StudentIdProperty, value); }
}

public static DependencyProperty StudentNameProperty =
DependencyProperty.Register("StudentName", typeof(string), typeof(StudentViewModel));
public string StudentName
{
get { return (string)GetValue(StudentNameProperty); }
set { SetValue(StudentNameProperty, value); }
}

#endregion Dependency Properties

#region Overriden methods of DependencyObject
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
switch (e.Property.Name)
{
case "StudentId":
_model.StudentId = (int)e.NewValue;
break;
case "StudentName":
_model.StudentName = (string)e.NewValue;
break;
}
}
#endregion Overriden methods of DependencyObject
}

We have update the properties StudentId and StudentName to be Dependency properties. To synchronize the model's corresponding properties we have overridden OnPropertyChanged method of DependencyObject. The argument DependencyPropertyChangedEventArgs , not only, provides us the details about the property being updated but it also provides the old and new values of this property. As you can see we are just using the new values of these properties to update the corresponding model's properties.

We have kept the handling of model's PropertyChanged event observation using Reactive extension's Observable event stream support available in CoreEx assembly. Let's run the application now and open two child windows.


When we enter StudentName in one child window, the same changes are reflected in the other child window.


Now we add throttling support in order to avoid frequent updates to the other child windows due to updates in model's properties. Let's update the constructor of StudentViewModel as follows:

public StudentViewModel(Student student)
{
_model = student;

Observable.FromEvent<PropertyChangedEventArgs>(_model, "PropertyChanged")
.Where(et => et.EventArgs.PropertyName == "StudentName")
.Throttle(TimeSpan.FromMilliseconds(500))
.Subscribe((arg) =>
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
});
}

This definition is same as previous. We have just used Throttling for PropertyChanged event for 500 milliseconds. Now we run the application. Open two child windows and enter data in StudentName property in one of the child window. As soon as we settle, the application shuts down. Let's see what is going on by updating the code further as follows:

public StudentViewModel(Student student)
{
_model = student;

Observable.FromEvent<PropertyChangedEventArgs>(_model, "PropertyChanged")
.Where(et => et.EventArgs.PropertyName == "StudentName")
.Throttle(TimeSpan.FromMilliseconds(500))
.Subscribe((arg) =>
{
try
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
});
}

Now we run the application and enter data in StudentName text box as previous. The exception handling logic causes the following MessageBox to be displayed.


This is because of the reason that IObservable.Throttle causes OnNext to be placed in a ThreadPool thread.


Using Invoke / BeginInvoke on Dispatcher:
The first solution could be to directly using Dispatcher.Invoke / Dispatcher.BeginInvoke. We can specify the code that we want to execute in the Action delegate. The delegate's code is executed here on UI thread. We update the constructor as follows:

public StudentViewModel(Student student)
{
_model = student;

Observable.FromEvent<PropertyChangedEventArgs>(_model, "PropertyChanged")
.Where(et => et.EventArgs.PropertyName == "StudentName")
.Throttle(TimeSpan.FromMilliseconds(500))
.Subscribe((arg) =>
{
Dispatcher.BeginInvoke(new Action(() =>
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
}), null);

});
}

Now we run the application. Again we open two windows and enter data in StudentName text box. We see that the data is successfully updated in the other window now. Let's insert the break point again in OnNext code.


Using other overload of Throttle:
We can use other overload of IObservable.Throttle method. This requires an additional overload which has an additional parameter of type IScheduler. IScheduler is a Rx interface available in CoreEx assembly and System.Concurrency namespace.

public StudentViewModel(Student student)
{
_model = student;

Observable.FromEvent<PropertyChangedEventArgs>(_model, "PropertyChanged")
.Where(et => et.EventArgs.PropertyName == "StudentName")
.Throttle(TimeSpan.FromMilliseconds(500), Scheduler.Dispatcher)
.Subscribe((arg) =>
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
});
}

We have specified Scheduler.Dispatcher for other parameter. This is also available in System.Concurrency namespace. It is available in CoreEx assembly. This is saving us from dispatching in our code but Throttle's generated OnNext messages will be generated in the UI thread. Let's run the application and open two child windows like before.


Download:

Sunday, February 13, 2011

MVVM - Joining Rx's IObservables using LINQ to IObservable in a WPF Application

In this post, we will see how we can combine two IObservable(s) using LINQ. The project is developed on top of the code as developed in this post:

http://shujaatsiddiqi.blogspot.com/2011/02/mvvm-view-model-iobserver-observing.html

We will just be discussing the changes required for this example. For the discussion of complete code please refer to the link provided above.

As in the previous post, the view model will be observing the data streams from to IObservable. It needs to combine them both using LINQ (as specified above). It would be interesting as we would see how data is combined when data is pushed by the IObservable. As soon as the data is available, it would automatically combine it using different operators provided by Reactive Extensions (Rx). Since we don't need to display data separately in the view, we update the view just to have one ListBox. The ListBox should show Id and Name of each Student. It should also show the name of the course the student is enrolled in, which could be obtained from observing CourseModel.


After completion of data stream, the use should be notified by changing the Fill color of ellipse as green. The expected final display is shown as follows:



To update the view as described above, we need to update the design of the view as follows:

<Window x:Class="WpfApp_MVVM_ReactiveModel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp_MVVM_ReactiveModel"
Title="MainWindow" Height="350" Width="525" >
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<ListBox Height="250" HorizontalAlignment="Left" Margin="-2,0,0,0"
Name="listBox1" VerticalAlignment="Top" Width="493"
ItemsSource="{Binding StudentList}">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding StudentId, StringFormat=Id:{0}}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding StudentName, StringFormat=Name:{0}}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding CourseName, StringFormat=Name:{0}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Ellipse Height="39" HorizontalAlignment="Left" Margin="370,257,0,0"
Name="ellipse1" Stroke="Black" VerticalAlignment="Top" Width="116" >
<Ellipse.Style>
<Style TargetType="{x:Type Ellipse}">
<Style.Setters>
<Setter Property="Fill" Value ="Blue" />
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding IsLoaded}" Value="true" >
<Setter Property="Fill" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</Grid>
</Window>

The view is still using MainWindowViewModel as DataContext. You can see that an additional TextBlock is added to the template of items of ListBox. It is bound to CourseName from each item of the collection bound to the list box. The DataContext is expected to have a collection StudentList with items having properties StudentId, StudentName and CourseName. This is implemented as an ObservableCollection so that as the items are entered in the collection, the view could update itself using the notification mechanism built-in for this type of collection. It should also have a boolean property, IsDataLoaded. It should turn true when data is completely loaded. This is used in DataTrigger in the view to turn the notification ellipse to be filled as Green. We need to implement INotifyPropertyChanged just because of this property so that view can be notified for this change and the data triggered could trigger the fill color of the ellipse.

class MainWindowViewModel : INotifyPropertyChanged
{
private readonly ObservableCollection<StudentViewModel> _studentList =
new ObservableCollection<StudentViewModel>();

public ObservableCollection<StudentViewModel> StudentList
{
get { return _studentList; }
}

private bool _isLoaded = false;
public bool IsLoaded
{
get { return _isLoaded; }
set
{
_isLoaded = value;
onPropertyChanged("IsLoaded");
}
}

public MainWindowViewModel()
{
var courseModel2 = new CourseModel();
var studentModel2 = new StudentsModel();

(from c in courseModel2
from s in studentModel2
where s.CourseId == c.CourseId
select new { s.StudentName, s.StudentId, c.CourseName })
.Subscribe(
(on) => _studentList.Add(new StudentViewModel(on)),
(ex) => Console.WriteLine(@"On error"),
() => IsLoaded = true);

}

#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
#endregion INotifyPropertyChanged implementation
}

The focal point of this post is the constructor of MainWindowViewModel. Here we are combining to IObservable based collections using LINQ. This is a special new flavor of LINQ released with Rx. This is called LINQ to IObservable. This is available in System.Reactive assembly. Let's have a close look at the constructor.
>
public MainWindowViewModel()
{
var courseModel2 = new CourseModel();
var studentModel2 = new StudentsModel();

(from c in courseModel2
from s in studentModel2
where s.CourseId == c.CourseId
select new { s.StudentName, s.StudentId, c.CourseName })
.Subscribe(
(on) => _studentList.Add(new StudentViewModel(on)),
(ex) => Console.WriteLine(@"On error"),
() => IsLoaded = true);

}

So we are cross-joining instances of CourseModel and StudentsModel. This would be creating a Cartesian Product. We are filtering it for only those which have matching CourseId(s).

As specified in the definition of the view, we are interested in StudentId and StudentName from StudentsModel and CourseName from CourseModel.

The cross product of Cartesian Product of two or more IObservable(s) is also an IObservable. This enables us to subscribe to it by providing the OnNext, OnCompleted and OnError of Observer. It is to remember that MainWindowViewModel is not the observable for the new IObservable created by combining CourseModel and StudentsModel. Rx run-time would take care of how the provided lambda expressions for OnNext, OnCompleted and OnError are to be executed.

The overload of Subscribe method that we have used takes three arguments OnNext, OnError and OnCompleted respectively. We are not doing anything useful in the lambda expression provided for OnError except just writing on the exception message on the console. In the OnCompleted expressoin we are setting IsLoaded to true. This would trigger the DataTrigger in the view and change the fill color of Notification ellipse to Green. The type of parameter of OnNext is the anonymous type created for Select. This would have same elements with similar names. As we have data available in OnNext, we are creating a StudentViewModel object and add it to the StudentsList ObservableCollection . This is bound to the ListBox in the view which would show this new element. Though we can not use foreach for IObservable as it is a feature of just IEnumerable, we can understand it by this nested foreach loop. Don't even try this:


Since the combined collections have IObservable based, we don't have the data available at the same time. This makes it very special form of joining. This would keep each element of courseModel2 in memory until OnCompleted is not executed from studentModel2. As the elements are being received in background OnNext for studentModel they are combined with each element of courseModel. This would be creating equal number of Observers for studentModel2 as the total number of elements pushed by courseModel2. As the elements of courseModel2 continue to be received they are added to the list of Observers of studentModel2.


We should be able to safely make a summarized statement about it as follows:

All the elements pushed through OnNext of courseModel2 would be combined with all the elements pushed by studentModel2. If there is any OnNext of either of these IObservable before this LINQ, that would not be considered for joining.


As soon as the OnCompleted is executed for this Observer created at runtime, it would automatically unsubscribe it by disposing itself. As we have seen in previous posts that disposing an unsubscriber would result in its unsubscription. I think this is the default implementation provided for this dynamic Observer by Rx runtime.

This would need updates in StudentViewModel. We need to add a property CourseName as used in MainWindowViewModel. There is one more interesting thing, the datatype of parameter for constructor is specified as dynamic. This is basically because of anonymous type constructed during LINQ operation. In the constructor, we are using it as a duck type datatype, we know what properties would it have but we don't know it's name as it would be assigned any arbitrary name at run-time. This is a special feature of .net framework 4.0 [http://msdn.microsoft.com/en-us/library/dd264736.aspx].

class StudentViewModel : INotifyPropertyChanged
{
public StudentViewModel(dynamic student)
{
this.StudentId = student.StudentId;
this.StudentName = student.StudentName;
this.CourseName = student.CourseName;
}

private string _courseName;
public string CourseName
{
get { return _courseName; }
set
{
_courseName = value;
OnPropertyChanged("CourseName");
}
}

private string _studentName;
public string StudentName
{
get { return _studentName; }
set
{
_studentName = value;
OnPropertyChanged("StudentName");
}
}

private int _studentId;
public int StudentId
{
get { return _studentId; }
set
{
_studentId = value;
OnPropertyChanged("StudentId");
}
}

#region INotifyPropertyChanged implementation

public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

#endregion INotifyPropertyChanged implementation
}

So we need to update Student to add a new property, CourseId. This would be used as a key to join StudentsModel and CourseModel IObservable collections. This is int type.
>
class Student
{
public string StudentName { get; set; }
public int StudentId { get; set; }
public int CourseId { get; set; }
}

Since we have updated Student type, we need to update the definition for StudentsModel. This is to specify value of CourseId. We are just deriving it based on a algorithm [If _studentId is odd then set CourseId as 2, otherwise, set it as 1]. We are also reducing the number of times that timer event would execute. You can see that we are calling Observer's OnCompleted just when the event has been executed 3 times. As we call OnCompleted on Observer, we are also stopping the timer, this would not keep the timer running on the background.
>
class StudentsModel : IObservable<Student>
{
private int _studentId = 1;

//Timer to notify observers about updates in the reactive observable
private readonly DispatcherTimer _t = new DispatcherTimer();

public List<IObserver<Student>> Observers =
new List<IObserver<Student>>();

public StudentsModel()
{
_t.Interval = TimeSpan.FromMilliseconds(3000);
_t.Tick += new EventHandler(Tick);
_t.Start();
}

void Tick(object sender, EventArgs e)
{
var student = new Student()
{
StudentId = _studentId,
StudentName = string.Format("Student: {0}", _studentId),
CourseId = ((int)(_studentId % 2)) + 1
};

if (_studentId <= 3)
{
Observers.ForEach((observer) => observer.OnNext(student));
_studentId++;
}
else
{
Observers.ForEach((observer) => observer.OnCompleted());
_t.Stop();
}
}

public IDisposable Subscribe(IObserver<Student> observer)
{
IDisposable unSubscriber = new Unsubscriber<Student>(Observers, observer);
if (!Observers.Contains(observer))
{
Observers.Add(observer);
}
return unSubscriber;
}
}

Now Let's run the application. The application runs successfully and we see the elements being added to the list box.



But there is a weird thing. The notification ellipse is still filled as blue. It should have turned Green if OnCompleted of the LINQ result is executed in MainWindowViewModel. It means that OnCompleted ,for this, is not executed. You can prove that by inserting break point in the lambda expression used for OnCompleted. But the main question is why it is not executed??

Basically, we have discussed that equal numbers of Observers would be created for studentModel2 as the number of elements pushed by courseModel2 after the LINQ statment is executed. So there are will be two observers for this. If we insert break-point in the Tick event handler for timer _t in StudentsModel then we realize that OnCompleted is executed only once. We need to execute OnCompleted for all observers to fix this. This is really weird because we are using Foreach on Obsevers List. It should have executed the OnCompleted for all observers. There should have been no Observer in the list before next statement is executed [_t.Stop()]. But if we put a break point then it seems that OnCompleted is executed only once as one Observer is still lingering on.


This seems to get fixed if we update the code as follows:

void Tick(object sender, EventArgs e)
{
var student = new Student()
{
StudentId = _studentId,
StudentName = string.Format("Student: {0}", _studentId),
CourseId = ((int)(_studentId % 2)) + 1
};

if (_studentId <= 3)
{
Observers.ForEach((observer) => observer.OnNext(student));
_studentId++;
}
else
{
Observers.ToList().ForEach((observer) => observer.OnCompleted());
_t.Stop();
}
}

Now run this and insert the break point appropriately.



We have just called ToList() on a collection which is already a Generic List to fix this. This shows some issue with the deferred execution of Lambdas of foreach here, which is executing OnCompleted for each observer. This would definitely introduce some performance delay but whatever works...

Now since all the OnCompleted have been executed for all the collections involved in the LINQ query, it is safe to executed the OnCompleted of the result. Rx runtime does exactly that. This sets IsLoaded to true and results in filling the Notification ellipse as Green.



Download Code:

Thursday, February 10, 2011

MVVM - Observable INotifyPropertyChanged.PropertyChanged Event Stream Using Reactive Extension

In this post we are going to discuss how we can use observable event streams using Reactive Extension. Since we have been trying to apply this knowledge to MVVM and seeking what benefit we can obtain from Rx, we will be mostly interested in those events which we deal with the most frequently. One such event is PropertyChanged event of INotifyPropertyChanged.

Let’s start with a sample WPF application. As is general in this blog, We will start with a very simple example. Then we will keep adding complexity to it and discuss why we actually need them. Below is a typical WPF window. It just has a button. We need to show another window to enter the details about student.

<Window x:Class="WpfApp_MVVM_ReactiveModelSynch.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Show Student Form" Height="47" HorizontalAlignment="Left"
Margin="104,244,0,0" Name="button1" VerticalAlignment="Top" Width="318" Click="button1_Click" />
</Grid>
</Window>

Since these details need to be shared between different StudentView windows, we are defining the Student object as instance variable. When user clicks the window, we are constructing the view model on the fly but we keep passing the same Student instance. This would enable the information to be shared between different windows. We are calling Show() on this new instance of StudentView. As you know this would show this window as a Modeless window. This is to demonstrate the scenarios in which we might not instantiate view models inside the view but we need to hand it over, somehow, to the view.

public partial class MainWindow : Window
{
private Student _student;

public MainWindow()
{
InitializeComponent();

_student = new Student();
}

private void button1_Click(object sender, RoutedEventArgs e)
{
new StudentView(new StudentViewModel(_student)).Show();
}
}



Now we have a look at the definition of StudentView. It just has two text boxes for user entry. The information regarding Id and Name of Student can be entered in those text boxes. These text boxes are bound to StudentId and StudentName properties from the DataContext.

<Window x:Class="WpfApp_MVVM_ReactiveModelSynch.StudentView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StudentView" Height="300" Width="484">
<Grid>
<Label Content="Id" Height="26" HorizontalAlignment="Left" Margin="11,30,0,0"
Name="labelId" VerticalAlignment="Top" Width="73" />
<TextBox Height="26" HorizontalAlignment="Left" Margin="90,30,0,0"
Name="textBoxId" VerticalAlignment="Top" Width="362"
Text="{Binding Path=StudentId, UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="Name" Height="25" HorizontalAlignment="Left" Margin="11,76,0,0"
Name="labelName" VerticalAlignment="Top" Width="73" />
<TextBox Height="26" HorizontalAlignment="Left" Margin="90,75,0,0" Name="textBoxName"
VerticalAlignment="Top" Width="362"
Text="{Binding Path=StudentName, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>

In the code behind, we assign the view model passed as constructor argument to the DataContext property of the view.

public partial class StudentView : Window
{
public StudentView(StudentViewModel studentViewModel)
{
InitializeComponent();

this.DataContext = studentViewModel;
}
}



As is expected by the view, StudentViewModel has two properties StudentId and StudentName. Both support change notification using INotifyPropertyChanged’s PropertyChanged event. As is specified in the MainWindow.xaml.cs, we are using Student object as constructor parameter. We are assigning it to the instance variable _model. We are using _model as Model for this view. WPF Binding system would update the values of these properties as the user enters data in the text boxes bound to these properties. In the setters of these properties, we are just assigning these values to the corresponding properties in _model. This should keep model being updated. Since this is shared by the view models used by each StudentView object, we expect the other views to be updated as these changes are applied.

public class StudentViewModel : INotifyPropertyChanged
{
private int _studentId;
private string _studentName;

private Student _model;

public StudentViewModel(Student student)
{
_model = student;
}

public int StudentId
{
get { return _studentId; }
set
{
if (_studentId != value)
{
_studentId = value;
_model.StudentId = value;
OnPropertyChanged("StudentId");
}
}
}

public string StudentName
{
get { return _studentName; }
set
{
if(_studentName != value)
{
_studentName = value;
_model.StudentName = value;
OnPropertyChanged("StudentName");
}
}
}

public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

As you might have guessed from the above code, Student has two properties StudentId and StudentName. This also implements INotifyPropertyChanged so needs to define PropertyChanged event. Whenever the values of these properties are changed, PropertyChanged event is raised to notify all observers about this change. Though it does not provide the actual change but it does tell about the property updated. We can handle this event in the code using StudentModel and act accordingly.

public class Student : INotifyPropertyChanged
{
private int _studentId;
private string _studentName;

public int StudentId
{
get { return _studentId; }
set
{
if (_studentId != value)
{
_studentId = value;
OnPropertyChanged("StudentId");
}
}
}

public string StudentName
{
get { return _studentName; }
set
{
if (_studentName != value)
{
_studentName = value;
OnPropertyChanged("StudentName");
}
}
}

public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

Now let’s run this! We open two StudentView windows. We enter data in one window. The data is not being updated in the second window. Why is this?? As is apparent in the code of view model, as we receive updates in View Model’s properties through WPF Binding System, we are passing the same updates to the corresponding properties in the model.


If you put break points in the model properties’ setter, you would notice that the setter code is being executed. Even the PropertyChanged event is being raised. We just need to handle this event in the view model so that the view model could update its properties. Since these properties are supporting change notifications using INotifyPropertyChanged, the bound element in the view should also be updated accordingly. As discussed, let’s subscribe PropertyChanged event in the view model for model object.
_model.PropertyChanged += new PropertyChangedEventHandler(_model_PropertyChanged);

The definition of _model_PropertyChanged is as follows:

void _model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
object value = _model.GetType().GetProperty(e.PropertyName).GetValue(_model, null);
this.GetType().GetProperty(e.PropertyName).SetValue(this, value, null);
}

This is based on reflection and based on the assumption that View Model has properties with same names. Their types are also assumed to be supportive. Since we only have limited properties, we can also avoid reflection and update each property. Let’s do that.

void _model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
}

Now let’s run this application. We will again open two windows and enter data in one window and observe if the same updates are made in the second window.


As expected, the updates are applied in the second window.

Now since we have fulfilled whatever the requirements have stated, we should be the happiest person in the world. But we can certainly improve on this implementation. We needed to handle model’s PropertyChanged event in StudentViewModel. We can avoid these by using observable event stream support available in Reactive Extension (Rx). Not only it allows to subscribe to the observable event stream, it also allows a filtered subscription. So We will be subscribing to a subset of events using Where clause even if there is an active event stream. It is also possible that we are receiving frequent updates from the model, like millions in a second. We don’t want to update our view so frequently. Similarly, since we have set UpdateSourceTrigger as PropertyChanged for both binding in the view. All the changes in the Text property of the text box will cause the property setter to execute. It is possible that the user of this system types very frequently, we might just want to update the model when it settles and not after each key entry. In short we might need throttling support for these property changes.

Using Observable Event Stream for model’s PropertyChanged event:
Before adding the code described in this section remove model’s PropertyChanged handling logic from StudentViewModel. This includes event subscription in the constructor and definition of event handler. Before making the updates suggested above, we need to reference assemblies provided by Rx installer. We need to add references for following assemblies:

1. System.Reactive.dll
2. System.CoreEx


These assemblies are installed as part of installation of Reactive Extension (Rx). It can be downloaded as follows:

http://msdn.microsoft.com/en-us/devlabs/ee794896

Update the code of the constructor of StudentViewModel as follows:

public StudentViewModel(Student student)
{
_model = student;

Observable.FromEvent<PropertyChangedEventArgs>(_model, "PropertyChanged")
.Subscribe((arg) =>
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
});
}

System.Linq.Observable from System.Reactive assembly allows to subscribe with any event stream. System.Collections.Generic.IEvent<T> is defined in System.CoreEx assembly. We are subscribing to PropertyChanged event stream from _model instance. Observable.FromEvent<T>() returns IObservable<IEvent<T>>. Since it is an IObservable, we can subscribe to it. The code that we want to execute when event is triggered can be specified in the onNext delegate. Let's run the application now.



Like before, we are opening two instances of StudentView window. When we enter information in the text boxes, information is updated in other window. The contents are updated because of the event handling logic in the observable event stream handler code as presented above.

Filtering events from Event Stream:
Since it is an IObservable<T> we can filter it using Where operator. Let's filter it to just handle the case when event is received because of update in StudentName property. The changes in StudentId are ignored. Let's update the code as follows:

public StudentViewModel(Student student)
{
_model = student;

Observable.FromEvent<PropertyChangedEventArgs>(_model, "PropertyChanged")
.Where(et => et.EventArgs.PropertyName == "StudentName")
.Subscribe((arg) =>
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
});
}

Now run the application and again open two instances. The update in text box for StudentName shows the updates in the other window. If we update StudentId, it doesn't update the other window as the event stream is filtered.



Throttling events from Event Stream:
Since are binding using UpdateSourceTrigger as PropertyChanged, as the user types in the text boxes in StudentView, WPF Binding System automatically updates the values in the View model's properties. This updates corresponding properties of the model using the view model's property setters. We just don't want to keep sending updates to the model but we should wait until the user is done typing and then update the model's properties. This can be supported by throttling support. This can by achieved introducing PropertyChanged event in the view models for itself. We can remove the code to update corresponding model's properties in the setters. Let's update the definition of StudentViewModel as follows:

public class StudentViewModel : INotifyPropertyChanged
{
private int _studentId;
private string _studentName;

private Student _model;

public StudentViewModel(Student student)
{
_model = student;

Observable.FromEvent<PropertyChangedEventArgs>(_model, "PropertyChanged")
.Where(et => et.EventArgs.PropertyName == "StudentName")
.Subscribe((arg) =>
{
this.StudentId = _model.StudentId;
this.StudentName = _model.StudentName;
});



Observable.FromEvent<PropertyChangedEventArgs>(this, "PropertyChanged")
.Throttle(TimeSpan.FromMilliseconds(500))
.Where(et => et.EventArgs.PropertyName == "StudentName")
.Subscribe((ar) =>
{
_model.StudentId = this.StudentId;
_model.StudentName = this.StudentName;
});

}

//void _model_PropertyChanged(object sender, PropertyChangedEventArgs e)
//{
// //object value = _model.GetType().GetProperty(e.PropertyName).GetValue(_model, null);
// //this.GetType().GetProperty(e.PropertyName).SetValue(this, value, null);
// //this.StudentId = _model.StudentId;
// //this.StudentName = _model.StudentName;
//}

public int StudentId
{
get { return _studentId; }
set
{
if (_studentId != value)
{
_studentId = value;
//_model.StudentId = value;
OnPropertyChanged("StudentId");
}
}
}

public string StudentName
{
get { return _studentName; }
set
{
if(_studentName != value)
{
_studentName = value;
//_model.StudentName = value;
OnPropertyChanged("StudentName");
}
}
}

public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

We needed to remove the code resulting in the updates in the setter of properties in the view model. Let' throttle these updates. When user types in StudentName, the IObservable doesn't update the other window immediately. It is rather waiting for property to settle down. After which it is causing the PropertyChanged events to be handled.



Download:

MVVM - View Model (IObserver) Observing multiple IObservable (s)

This is a continuation of posts of our discussion about the usage of Reactive Extension (Rx) in MVVM implementation in WPF. For this post, we will be trying to find out how a View model observes multiple observables. The main question is, Can an IObserver observes multiple IObservable?

In this example, view model is observing the data from different sources. We want to show the list of students and courses on the same window. I am not saying this is the best thing or I would do it in a real world application. But this is more of a what if kind of a scenario. We want our view to look like this:



Let us update the view in the previous post as follows:

<Window x:Class="WpfApp_MVVM_ReactiveModel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp_MVVM_ReactiveModel"
Title="MainWindow" Height="544" Width="526">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Label Content="Students" Height="26" HorizontalAlignment="Left" Name="label1"
VerticalAlignment="Top" Width="161" FontWeight="Bold" />
<ListBox Height="234" HorizontalAlignment="Left" Margin="4,30,0,0"
Name="listBox1" VerticalAlignment="Top" Width="493"
ItemsSource="{Binding StudentList}">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding StudentId, StringFormat=Id:{0}}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding StudentName, StringFormat=Name:{0}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Label Content="Courses" FontWeight="Bold" Height="26" HorizontalAlignment="Left" Margin="0,270,0,0"
Name="label2" VerticalAlignment="Top" Width="161" />
<ListBox Height="161" HorizontalAlignment="Left" Margin="5,294,0,0" Name="listBoxCourse"
VerticalAlignment="Top" Width="492"
ItemsSource="{Binding CourseList}">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CourseId, StringFormat=Id:{0}}" />
<TextBlock Text=" " />
<TextBlock Text="{Binding CourseName, StringFormat=Name:{0}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Ellipse Height="31" HorizontalAlignment="Left" Margin="326,462,0,0" Name="ellipse1"
Stroke="Black" VerticalAlignment="Top" Width="166" >
<Ellipse.Style>
<Style>
<Setter Property="Ellipse.Fill" Value="Yellow" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsDataStreamFinished}" Value="true">
<Setter Property="Ellipse.Fill" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</Grid>
</Window>

As you might have noticed we have thrown in a couple of labels to identify the data loaded in the two list boxes. The difference is we have incorporated another list box to show the list of Courses. It is bound to CourseList in the view model. Each member of this collection should have two properties i.e. CourseId and CourseName.

As we described above the view model is expected to have a collection called CourseList and each member of this collection should be having two properties CourseId and CourseName. Let us see what updates we need to make in the view model.

class MainWindowViewModel : IObserver<Student>, INotifyPropertyChanged, IObserver<Course>
{
#region Properties

private ObservableCollection<StudentViewModel> _studentList;
public ObservableCollection<StudentViewModel> StudentList
{
get { return _studentList; }
set
{
_studentList = value;
onPropertyChanged("StudentList");
}
}

private ObservableCollection<CourseViewModel> _courseList;
public ObservableCollection<CourseViewModel> CourseList
{
get { return _courseList; }
set
{
_courseList = value;
onPropertyChanged("CourseList");
}
}

private bool _isDataStreamFinished;
public bool IsDataStreamFinished
{
get { return _isDataStreamFinished; }
set
{
_isDataStreamFinished = value;
onPropertyChanged("IsDataStreamFinished");
}
}

#endregion Properties

#region Observable Model
//Model
private StudentsModel model;
private CoursesModel courseModel;

#endregion Observable Model

IDisposable unsubscriber;

#region Constructor

public MainWindowViewModel()
{
_studentList = new ObservableCollection<StudentViewModel>();

model = new StudentsModel();

//subscribe to all updates
//model.Subscribe(this);

//subscribe to 10 updates after first 2 updates
//unsubscriber = model.Skip(2).Take<Student>(10).Subscribe(this);

//subscribe to all students whose Ids are even
//unsubscriber = (from m in model
// where m.StudentId % 2 == 0
// select m).Subscribe(this);

//observe on UI thread
unsubscriber = Observable.ObserveOnDispatcher<Student>(
(from m in model
where m.StudentId % 2 == 0
select m)
).Subscribe(this);

courseModel = new CoursesModel();
_courseList = new ObservableCollection<CourseViewModel>();
Observable.ObserveOnDispatcher<Course>(courseModel).Subscribe(this);

}

#endregion Constructor

#region IObserver implementation
public void OnCompleted()
{
//throw new NotImplementedException();
//unsubscriber.Dispose();
IsDataStreamFinished = true;
}

public void OnError(Exception error)
{
//throw new NotImplementedException();
}

public void OnNext(Student value)
{
//throw new NotImplementedException();
_studentList.Add(new StudentViewModel(value));
}

#endregion IObserver implementation

#region INotifyPropertyChanged implementation

public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}

#endregion INotifyPropertyChanged implementation


public void OnNext(Course value)
{
//throw new NotImplementedException();
_courseList.Add(new CourseViewModel(value));
}
}

You should notice that the view model is not implementing IObserver<Course>;. This would enable it to observe an IObservable<Course>. It has been introduced with one IObservable<Course> instance named courseModel. We have also subscribed to this in the constructor to observe the courseModel on Dispatcher. To implement the interface, we need to provide the definition of three methods, OnNext, OnCompleted and OnError. Since OnCompleted and OnError are already provided so we don't need to provide a new definition, even, we can not implement as this would be considered as overloading the methods and this requires the methods, being overloaded, to have different signatures. In the OnNext(Course) method, we are adding a new CourseViewModel to CourseList collection.

Now let us provide the definition CourseModel. This is an IObservable<Course>. This would require it to provide an implementation of Subscribe() method. This method should accept IObserver<Course> and should return an IDisposable. Disposing this returned object should result in the nullify the subscription. This definition is similar to StudensModel.

class CoursesModel : IObservable<Course>
{
private int _courseId;
//For updates on a non-UI thread
Timer t = new Timer(1000);

public List<IObserver<Course>> Observers =
new List<IObserver<Course>>();

public CoursesModel()
{
t.Elapsed += new ElapsedEventHandler(t_Elapsed);
t.Start();
}

//For updates on a non-UI thread
void t_Elapsed(object sender, ElapsedEventArgs e)
{
_courseId++;

var course = new Course()
{
CourseId = _courseId,
CourseName = string.Format("Course : {0}", _courseId)
};

if (_courseId <= 3)
{
Observers.ForEach((observer) => observer.OnNext(course));
}
else
{
Observers.ForEach((observer) => observer.OnCompleted());
t.Stop();
}
}

public IDisposable Subscribe(IObserver<Course> observer)
{
IDisposable unSubscriber = new Unsubscriber<Course>(Observers, observer);
if (!Observers.Contains(observer))
{
Observers.Add(observer);
}
return unSubscriber;
}
}

The definition of Course and CourseViewModel are as follows:

class Course
{
public string CourseName { get; set; }
public int CourseId { get; set; }
}

class CourseViewModel : INotifyPropertyChanged
{
public CourseViewModel(Course course)
{
this.CourseId = course.CourseId;
this.CourseName = course.CourseName;
}

#region Properties

private string _coursetName;
public string CourseName
{
get { return _coursetName; }
set
{
_coursetName = value;
OnPropertyChanged("CourseName");
}
}

private int _courseId;
public int CourseId
{
get { return _courseId; }
set
{
_courseId = value;
OnPropertyChanged("CourseId");
}
}

#endregion Properties

#region INotifyPropertyChanged implementation

public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

#endregion INotifyPropertyChanged implementation
}

Now run the application. It is successfully loading the data as desired but there is a problem. The courseModel data is loaded first. This causes OnCompleted to be executed which fills the notification ellipse as green. So we are giving the notification to the user that the data is completely loaded even before it is completely loaded.



So, an IObserver can observe multiple IObservable (s) but we really can not distinguish between OnCompleted and OnError being executed because of which IObservable. We need to find out way to do that.

There is an easier solution to this problem. We can implement the interfaces explicitly. Let us assume that the notification is just about StudentList. The ellipse should turn green only when the StudentList is loaded completely. Let us implement IObserver<Course>.

class MainWindowViewModel : IObserver<Student>, INotifyPropertyChanged, IObserver<Course>
{
#region Properties

private ObservableCollection<StudentViewModel> _studentList;
public ObservableCollection<StudentViewModel> StudentList
{
get { return _studentList; }
set
{
_studentList = value;
onPropertyChanged("StudentList");
}
}

private ObservableCollection<CourseViewModel> _courseList;
public ObservableCollection<CourseViewModel> CourseList
{
get { return _courseList; }
set
{
_courseList = value;
onPropertyChanged("CourseList");
}
}

private bool _isDataStreamFinished;
public bool IsDataStreamFinished
{
get { return _isDataStreamFinished; }
set
{
_isDataStreamFinished = value;
onPropertyChanged("IsDataStreamFinished");
}
}

#endregion Properties

#region Observable Model
//Model
private StudentsModel model;
private CoursesModel courseModel;

#endregion Observable Model

IDisposable unsubscriber;

#region Constructor

public MainWindowViewModel()
{
_studentList = new ObservableCollection<StudentViewModel>();

model = new StudentsModel();

//subscribe to all updates
//model.Subscribe(this);

//subscribe to 10 updates after first 2 updates
//unsubscriber = model.Skip(2).Take<Student>(10).Subscribe(this);

//subscribe to all students whose Ids are even
//unsubscriber = (from m in model
// where m.StudentId % 2 == 0
// select m).Subscribe(this);

//observe on UI thread
unsubscriber = Observable.ObserveOnDispatcher<Student>(
(from m in model
where m.StudentId % 2 == 0
select m)
).Subscribe(this);

courseModel = new CoursesModel();
_courseList = new ObservableCollection<CourseViewModel>();
Observable.ObserveOnDispatcher<Course>(courseModel).Subscribe(this);

}

#endregion Constructor

#region IObserver implementation
public void OnCompleted()
{
//throw new NotImplementedException();
//unsubscriber.Dispose();
IsDataStreamFinished = true;
}

public void OnError(Exception error)
{
//throw new NotImplementedException();
}

public void OnNext(Student value)
{
//throw new NotImplementedException();
_studentList.Add(new StudentViewModel(value));
}

#endregion IObserver implementation

#region INotifyPropertyChanged implementation

public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}

#endregion INotifyPropertyChanged implementation


void IObserver<Course>.OnCompleted()
{
//throw new NotImplementedException();
}

void IObserver<Course>.OnError(Exception error)
{
//throw new NotImplementedException();
}

void IObserver<Course>.OnNext(Course value)
{
_courseList.Add(new CourseViewModel(value));
}
}

Now when CoursesModel calls OnCompleted on the observers the explicit implementation of the interface's OnCompleted gets called which currently no implementation (just an empty method). So the ellipse is still yellow.



After the data is completely loaded, StudentsModel, an IObservable<Student> calls OnCompleted which sets the variable bound to the trigger on the view to change the fill color of ellipse to green.



Download: