RX自动完成框

4
我正在尝试使用RX和WPF构建过滤器控件。因此,我有一个文本框和一个列表框。启动时,列表框中有100个联系人姓名,用户可以输入姓名来过滤列表。
问题是如何建立一个文本流(键盘输入),然后发布它。这应该是时间敏感的,所以我猜只有在750毫秒后如果没有检测到键盘输入,则可以执行过滤器。
谢谢。
4个回答

7
基本概述如下:
  1. 将文本框按键事件转换为IO
  2. 限制击键速度,以便在用户实际输入时不搜索
  3. 执行搜索
  4. 将搜索结果放置到列表框中
这是一些伪代码 -
 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 不会每 750ms 就启动一次搜索,只有在用户停止输入超过 750ms 后才会启动。在 LinqPad 中尝试一下。

   Observable.Interval(TimeSpan.FromMilliseconds(10))
   .Do(ii =>  "keystroke".Dump())
   .Take(10)
   .Throttle(TimeSpan.FromSeconds(0.750))
   .Select(ttl => "search")

谢谢回复,Throttle 的问题在于它每隔 0.750 就会触发,我需要的是当没有按键按下时,能够在 0.750 后触发某些操作。 - Andy
1
@Andy - Throttle会在等待_timeoutSpan_一段时间后才发出值。如果在此期间收到新值,则_timeoutSpan_等待将重置。 - Richard Szalay
我该如何在LinqPad中测试这个?它无法识别Observable类。 - Mohammed Noureldin

2

Scott Weinstein的建议是正确的。

此外,由于您想影响Gui控件,您必须确保在订阅之前使用ObserveOn调度程序或在某处使用调度程序,以使您回到调度器线程。

这对我有用:

 Observable.FromEvent<TextChangedEventArgs>(TextBox, "TextChanged")
                .Throttle(TimeSpan.FromSeconds(0.75), Scheduler.Dispatcher)
                .Select(obs => TextBox.Text)
                .Subscribe(TextChangedTo);

现在,在TextChangedTo(text)方法中,您将使用联系人姓名填充列表。

1
始终优先选择使用IDispatcher重载而不是ObserverOnDispatcher。前者能够让你一直处于UI线程上,而后者则是将你移回UI线程上。 - Richard Szalay
当然,如果没有节流器,您就不需要委托回调度程序,因为您永远不会离开它。任何使用计时器的 Rx 方法,包括 Throttle、Interval、BufferWithTime 等,都需要管理线程。 - Jim Wooley

1

在新版本的Rx中,Scheduler.Dispatcher已经消失了,并且似乎FromEvent与WPF不兼容。因此,对于任何需要解决方案的人,这里提供一个针对名为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));

0

这里有一个完整的例子在这里, 包括幻灯片和源代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接