Observed reactive expansion pattern

I am trying to understand the code below trying to use reactive extensions

IObservable<string> textChangedObservable = Observable.FromEventPattern<TextChangedEventArgs>(searchScrip, "TextChanged") .Select(evt => ((TextBox) sender).Text); textChangedObservable.Subscribe(OnNext, OnCompleted); private void OnNext(string s) { System.Diagnostics.Debug.Print("OnNext " + s + "\n"); } private void OnCompleted() { System.Diagnostics.Debug.Print("OnCompleted " + "\n"); } 

If I enter SEARC in the input field, the output looks

  • Onnext se
  • OnNext SEA
  • OnNext SEA
  • OnNext SEAR
  • OnNext SEAR
  • OnNext SEAR
  • OnNext SEARC
  • OnNext SEARC
  • OnNext SEARC
  • OnNext SEARC

    • Why does "S" not start OnNext?
    • Why is OnCompleted never called?
    • Why does OnNext call n-1 times on the nth character?
+6
source share
3 answers

It seems that you are subscribing to what is observed in your searchScrip_TextChanged handler.

This means that the first time searchScrip_TextChanged receives an S call, it has already happened before you connected the observable. So, of course, it does not work.

But now, when S pressed, you have one subscription, so when E is dialed, you get one SE . But since the searchScrip_TextChanged handler searchScrip_TextChanged called for E too, you now have two subscriptions to your observable.

So, when A is typed, you get two SEA because you have two observables. But again, searchScrip_TextChanged is called for A , so now you have three observables.

Etc etc. etc.

Events do not end automatically. You need to manually get rid of the subscription so that they end. This should make sense because this is what you do with regular event handlers that you want to stop.

You must create your observable when your form is loaded so that it will be created once.

It should look like this:

 IObservable<string> textChangedObservable = Observable.FromEventPattern<TextChangedEventArgs>(searchScrip, "TextChanged") .Select(evt => searchScrip.Text); IDisposable subscription = textChangedObservable .Subscribe( s => Debug.Print("OnNext " + s + "\n"), s => Debug.Print("OnCompleted\n")); 
+3
source

The problem here really has nothing to do with Rx.

1: Why does "S" not start OnNext?

Since the TextChanged event you are subscribing to did not fire on the first S.

2: Why is OnCompleted never called?

When you IObservable<T> .NET event as an IObservable<T> , you never receive OnError or OnCompleted . There is no concept of error or termination with a .NET event.

If there are two events: one for values ​​and one for completion, you can combine them like this:

 var values = Observable.FromEvent(...); var completion = Observable.FromEvent(...); var query = values.TakeUntil(completion); 

OnCompleted will now give the correct OnCompleted notification.

3: Why does OnNext call n-1 time on the nth character?

Because the TextChanged event you are subscribing to is fired in this way. As @ Kari-Antti noted, this can be a side effect of using the "routed property" event.

+2
source

Perhaps because you used RoutedPropertyChangedEventArgs?

How about using PropertyChangedEventHandler?

 Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>( h => yourModel.propertyChanged += h, h => yourModel.propertyChanged -= h) .Where(x => x.EventArgs.PropertyName = "your_property_name"); } 
-1
source

All Articles