Reputation: 6220
I have the standard reactive-ui routing set up for a WPF app, and I have an interface that ViewModel's can implement to provide title information.
public interface IHaveTitle
{
IObservable<string> Title { get; }
}
In one view model I'm doing the following (for demo purposes):
public IObservable<string> Title => Observable.Interval(TimeSpan.FromSeconds(5)).Select(_ => DateTime.Now.ToLongTimeString());
In my main window screen, I'm doing the following:
disposer(
ViewModel.Router.CurrentViewModel
.SelectMany(vm =>
((vm as IHaveTitle)?.Title.StartWith("") ??
Observable.Return("")).Select(s => string.IsNullOrEmpty(s) ? vm.UrlPathSegment : $"{vm.UrlPathSegment} > {s}"))
.ObserveOn(RxApp.MainThreadScheduler)
.BindTo(this, w => w.Title));
Where disposer
is the Action<IDisposable>
passed into the this.WhenActivated
extension method.
Now, when I navigate around, the title does change to reflect the UrlPathSegment
, and while on the primary view model the title updates to show the time every 5 seconds.
The problem I'm seeing however, is that even when I navigate to a different view model, the title observable on the primary view model is still leading to changes on the title.
My question really, is: How do I prevent this? Why isn't it detaching when I navigate away, given I'm selecting based on the CurrentViewModel
?
Upvotes: 1
Views: 270
Reputation: 178630
The problem is the use of SelectMany
. You're saying "every time the CurrentViewModel
changes, subscribe to this other observable". Since those observables never complete, they remain "active" forever.
You instead want to switch to the new observable:
disposer(
ViewModel.Router.CurrentViewModel
.Select(vm =>
((vm as IHaveTitle)?.Title.StartWith("") ??
Observable.Return("")).Select(s => string.IsNullOrEmpty(s) ? vm.UrlPathSegment : $"{vm.UrlPathSegment} > {s}"))
.Switch()
.ObserveOn(RxApp.MainThreadScheduler)
.BindTo(this, w => w.Title));
Upvotes: 6