0

我正在C#中使用Rx创建搜索页面实现。我创建了一个通用搜索方法来搜索关键字并在UI上添加结果列表。下面是代码:使用Rx.Net搜索实现

通用搜索方法:

public static IObservable<TResult> GetSearchObservable<TInput, TResult>(INotifyPropertyChanged propertyChanged, 
       string propertyName, TInput propertyValue, Func<TInput, TResult> searchFunc) 
      { 
       // Text change event stream 
       var searchTextChanged = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                ev => propertyChanged.PropertyChanged += ev, 
                ev => propertyChanged.PropertyChanged -= ev 
               ) 
                .Where(ev => ev.EventArgs.PropertyName == propertyName); 

       // Transform the event stream into a stream of strings (the input values) 
       var inputStringStream = searchTextChanged.Throttle(TimeSpan.FromMilliseconds(500)) 
                 .Select(arg => propertyValue); 

       // Setup an Observer for the search operation 
       var search = Observable.ToAsync<TInput, TResult>(searchFunc); 

       // Chain the input event stream and the search stream, cancelling searches when input is received 
       var results = from searchTerm in inputStringStream 
           from result in search(propertyValue).TakeUntil(inputStringStream) 
           select result; 

       return results; 
      } 

的搜索一般使用方法:

var rand = new Random(); 
      SearchObservable.GetSearchObservable<string, string>(this, "SearchString", SearchString, search => 
      { 
       Task.WaitAll(Task.Delay(500)); 

       return SearchString; 
      }) 
      .ObserveOnDispatcher() 
      .Subscribe(rese => 
      { 
       LstItems.Clear(); 

       LstItems.Add(SearchString); 

       // Heavy operation lots of item to add to UI 
       for(int i = 0; i < 200000; i++) 
       { 
        LstItems.Add(rand.Next(100, 100000).ToString()); 
       } 

       Result = rese; 
      }); 

有这码2个问题需要帮助解决这些:

  1. 在通用方法行from result in search(propertyValue).TakeUntil(inputStringStream)中传递的搜索关键字始终为null,因为propertyValue是字符串类型,因此将其作为值传递给方法。如何在搜索方法中发送更新的值?

  2. 当重UI操作已经对订阅方法如在加入一些大量的随机数的示例来完成。重复执行搜索时会导致此问题。最终UI块。我怎样才能解决这个问题?

对于第二点是否有任何方法来取消以前的UI操作并运行一个新的。这只是一个想法。但需要一些建议来解决这些问题。

回答

0
  1. 您可以通过一个函数读取属性值,即代替TInput propertyValue你的方法应该接受Func<TInput> propertyValueGetter

您还可以使用ReactiveUI库。在这种情况下,您的代码会是这个样子:

this.WhenAnyValue(vm => vm.SearchString) 
    .Throttle(TimeSpan.FromMilliseconds(500)) 
    .InvokeCommand(DoSearchString); 

DoSearchString = ReactiveCommand.CreateAsyncTask(_ => { 
    return searchService.Search(SearchString); 
}); 

DoSearchString.ObserveOn(RxApp.MainThreadScheduler) 
       .Subscribe(result => { 
        LstItems.Add(result); 
       }) 
  • 我不相信有这个问题,一般的答案。只需尽可能多地在TaskPool上执行操作,并且当数据准备好显示时,切换到UI线程ObserveOn。在你的情况下,你可以通过批次插入项目,而不是一次全部插入。