I'm trying to build an filter control using RX and WPF. So I have a textbox and a listbox. On start up the listbox has 100 contact names and the user can type in a name to f开发者_如何学Cilter the list.
Question is how can I build up an text stream (key inputs) and then publish. This should be Time sensitive so I guess only after 750milliseconds if a key input hasnt been detected then the filter may be performed.
Thanks
The basic outline would looks like so
- textbox keydown event converted to an IO
- throttling of the keystrokes, so that we don't search while the user is actually typing
- Do the search
- Place the the search results onto the list box
Here's some pseudo-code -
var keysIO = Observable.FromEvent<KeyDownEventHandler, RoutedEventArgs>(
h => new KeyDownEventHandler(h),
h => btn.KeyDown += h,
h => btn.KeyDown -= h));
var searchResults = keysIO.Throttle(TimeSpan.FromSeconds(0.750),Scheduler.Dispatcher);
searchResults.Subscribe(sr => { lb.Clear(); lb.AddRange(sr); });
@Andy, Throttle
won't kick off a search every 750ms, only after the user has stopped typing for 750ms. Try this in LinqPad.
Observable.Interval(TimeSpan.FromMilliseconds(10))
.Do(ii => "keystroke".Dump())
.Take(10)
.Throttle(TimeSpan.FromSeconds(0.750))
.Select(ttl => "search")
What Scott Weinstein is suggesting is correct.
Additionally, since you want to affect a Gui control, you have to make sure to either ObserveOn the Dispatcher or use the scheduler somewhere before you subscribe, to get you back to the dispatcher thread.
This worked for me:
Observable.FromEvent<TextChangedEventArgs>(TextBox, "TextChanged")
.Throttle(TimeSpan.FromSeconds(0.75), Scheduler.Dispatcher)
.Select(obs => TextBox.Text)
.Subscribe(TextChangedTo);
Now in the TextChangedTo(text)
method you would populate your list with contact names.
On new versions of Rx the Scheduler.Dispatcher has disappeared and FromEvent seems that does not work well with WPF, so, for anyone that needs a solution today here you have a working solution for a textbox named FilterText:
Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
h => this.FilterText.TextChanged += h,
h => this.FilterText.TextChanged -= h)
.Throttle(new TimeSpan(0, 0, 0, 0, 750))
.ObserveOnDispatcher()
.Subscribe(t => DoFiltering(this.FilterText.Text));
There's a full example here, with slides and source code
精彩评论