2017-09-25 39 views
2

我有一个包含关键字的反应性列表。用户可以添加或删除该列表中的关键字。该应用需要验证用户是否键入了其中一个关键字。 已经有类似的帖子,但它并没有在考虑采取灵活的清单: Using Reactive Extension for certain KeyPress sequences?验证用户是否从具有反应性扩展的反应性列表中键入单词

var keyElements = new ReactiveList<KeyElement>(); 
IObservable<IObservable<int>> rangeToMax = Observable.Merge(keyElements.ItemsAdded, keyElements.ItemsRemoved).Select(obs => Observable.Range(2, keyElements.Select(ke => ke.KeyTrigger.Length).Max())); 


IObservable<IObservable<string>> detectedKeyTrigger = rangeToMax 
    .Select(n => _keyPressed.Buffer(n, 1)) 
    .Merge().Where(m => keyElements.Where(ke => ke.KeyTrigger == m).Any()); 
//Here I want to end up with IObservable<string> instead of IObservable<IObservable<string>> 

我可以每次都重新分配detectedKeyTrigger元素在反应列表的变化摆脱外的IObservable的,但后来我失去了我所有的订阅。 那么,我怎样才能得到一个字符串的可观察?

+0

你能解决你的代码吗?它在'.Buffer(n,1)'后面或'.Any())'后面有一个括号。那你能不能请[mcve]?我希望能够编译和运行你的代码。 – Enigmativity

+0

@Enigmativity感谢花时间在我的问题上。我对示例代码做了一个小小的更新。同时,JonStødle提供了我正在寻找的答案。 – jtourlamain

+0

不用担心。将来,发布[mcve]会对你有好处。这会有很大的帮助。 – Enigmativity

回答

4

首先,MaxAny都有重载,它们分别带有一个选择器和一个谓词。这否定了Select的需要。

接下来,我改变了Observable.Merge使用的ReactiveListChanged财产是INotifyCollectionChanged在Rx版本。我也改变了Select来产生IEnumerableints。它只是感觉更正确™。

var keyElements = new ReactiveList<KeyElement>(); 
IObservable<IEnumerable<int>> rangeToMax = keyElements.Changed 
    .Select(_ => Enumerable.Range(2, keyElements.Max(keyElement => keyElement.KeyTrigger.Length)); 


IObservable<IObservable<string>> detectedKeyTrigger = rangeToMax. 
    .Select(range => range 
     .Select(length => _keyPressed.Buffer(length, 1).Select(chars => new string(chars.ToArray()))) // 1 
     .Merge() // 2 
     .Where(m => keyElements.Any(ke => ke.KeyTrigger == m)) // 3 
    .Switch(); // 4 
  1. 创建IObservable<string>发射最后n字符由用户键入。对于每次组合
  2. 的可能长度创建这样一个观察的合并在IEnumerable<IObservable<string>>的观测到一个Observable<string>
  3. 只有让马赫的KeyTrigger S的一个通过
  4. 作为rangeToMax.Select串产生IObservable<IObservable<string>>我们使用Switch只能订阅最近的IObservable<string>IObservable<IObservable<string>>产生。