0

I am trying to create an IObservable<string> from the following code, but i can't seem to find a way of how to properly unwrap the value of the event handler.

What is happening is that the PasswordBox might change, so whenever it does i want to observe on that, and provide a string resource whenever the password changed event is raised. It works fine if i do it with ordinary events but i am curious on how this would work using System.Reactive.

        var passwordChanged = WhenPropertyChanged
            .Where(name => nameof(PasswordBox) == name)
            .Select(d => PasswordBox)
            .Where(d => d != null)
            .Select(box =>
            {
                return Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
                    handler => box.PasswordChanged += handler,
                    handler => box.PasswordChanged -= handler);
            }).Select(d => nameof(Password));

to me it seems like there has to be some way within the Select(box => ... part where i can return a different object (other than IObservable<IObservable<RoutedEventArgs>>), which can be used to subscribe to properly.

Doing it like the following works. But i think reactive does a better job of avoiding event handler memory leaks if you use it end to end.

        var passwordHasChanged = new Subject<string>();
        // listen for changes of the password
        WhenPropertyChanged
            .Where(name => nameof(PasswordBox) == name)
            .Select(d => PasswordBox)
            .Where(d => d != null)
            .Subscribe(box =>
            {
                box.PasswordChanged += (sender, args) => passwordHasChanged.OnNext(nameof(Password));
            });

        passwordHasChanged.Subscribe(d => Log.Debug("Password changed"));
Dbl
  • 5,634
  • 3
  • 41
  • 66

1 Answers1

3

Avoid using Subjects wherever possible. Subjects are like the mutable variables of Rx, they don't compose and read imperatively rather than declaratively.

If you want events from only the last password input, use Switch.

Switch works on an IObservable<IObservable<T>>, and unsubscribes from the previous observable when it gets a newer observable.

   var passwordChanged = WhenPropertyChanged
            .Where(name => nameof(PasswordBox) == name)
            .Select(d => PasswordBox)
            .Where(d => d != null)
            .Select(box =>                
                Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
                    handler => box.PasswordChanged += handler,
                    handler => box.PasswordChanged -= handler);
            )
            .Switch()
            .Select(d => nameof(Password));
Asti
  • 12,447
  • 29
  • 38