I have an Entry Textbox that searches as the user types. I don’t want the search on every letter, but rather wait 0.5 seconds between typing then search on what the current Query Text is. So as the user types the Query builds a string. That string is searched on every 0.5 seconds, not after every keystroke.
Let’s say the user types CANADA, here’s what happens:
C {WAIT}
CA {WAIT}
CAN {Search}
CANA {WAIT}
CANAD {WAIT}
CANADA {SEARCH}
Here how:
In your XAML put a SearchBar with a Command (Behaviors):
<SearchBar Text="{Binding Query}" Placeholder="Search Address Book"> <SearchBar.Behaviors> <behaviors:EventHandlerBehavior EventName="TextChanged"> <behaviors:InvokeCommandAction Command="{Binding RefreshCommand}" /> </behaviors:EventHandlerBehavior> </SearchBar.Behaviors> </SearchBar>
When the user types we store the Text in the Model’s Query property and call the RefreshCommand in the model for changes. This is a common way to do searches.
Here’s the magic you need to put into your Model (thanks to SO)
public ICommand RefreshCommand => new Command(async () => { await DelayedQueryForKeyboardTypingSearches().ConfigureAwait(false); });
private CancellationTokenSource throttleCts = new CancellationTokenSource(); /// <summary> /// Runs in a background thread, checks for new Query and runs current one /// </summary> private async Task DelayedQueryForKeyboardTypingSearches() { try { Interlocked.Exchange(ref this.throttleCts, new CancellationTokenSource()).Cancel(); await Task.Delay(TimeSpan.FromMilliseconds(500), this.throttleCts.Token) .ContinueWith(async task => await Refresh() , CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext()); } catch { //Ignore any Threading errors } } }