icube
icube

Reputation: 2798

ReactiveUI/Reactive Extensions: how to clear ObservableAsPropertyHelper

I am using the ReactiveUI framework to do searching for a list of airports in the world.

I have setup the ObservableAsPropertyHelper that is the output of the suggested airports from a SearchTerm property in the ViewModel. The following is the definition for the ObservableAsPropertyHelper. In the view, I have a listbox that binds to this property. I would like to be able to clear the listbox explicitly(because once the user selected a suggested item, I want to populate the SearchTerm with the selected airport and clear the suggested list). Is there an elegant way to implement this?

var searchTerms = this.ObservableForProperty(x => x.SearchTerms).Where(x => canSearch).Value().Throttle(TimeSpan.FromMilliseconds(500));
var searchResults = searchTerms.SelectMany(SearchAirports);
var latestResults = searchTerms.CombineLatest(searchResults, (s, r) => r.SearchTerm != s ? null : r.AirportLiteWithWeights).Where(x => x != null);
_airportLiteWithWeights = latestResults.ToProperty(this, x => x.AirportLiteWithWeights);

Upvotes: 3

Views: 1194

Answers (1)

Ana Betts
Ana Betts

Reputation: 74654

Here's how I would do it - it's a bit tricky because the actual sequence of events feeds back into itself (i.e. selecting an item sets SearchTerms)

// The act of selecting an item is very ICommand'y, let's model it
// as such.
ReactiveCommand SuggestionItemSelected = new ReactiveCommand();

// Important to *not* signal a change here by touching the field
// so that we avoid a circular event chain
SuggestionItemSelected.Subscribe(x => _searchTerms = x);

// NB: Always provide a scheduler to Throttle!
var searchTerms = this.WhenAnyValue(x => x.SearchTerms)
    .Where(x => canSearch)
    .Throttle(TimeSpan.FromMilliseconds(500), RxApp.MainThreadScheduler);

// Select + Switch will do what you were trying to do with CombineLatest
var latestResults = searchTerms
    .Select(SearchAirports);
    .Switch()

// The listbox is the combination of *Either* the latest results, or the
// empty list if someone chooses an item
var latestResultsOrCleared = Observable.Merge(
    latestResults,
    SuggestionItemSelected.Select(_ => new List<Results>()));

latestResultsOrCleared
    .ToProperty(this, x => x.AirportLiteWithWeights, out _airportLiteWithWeights);

Upvotes: 2

Related Questions