验证用户是否从带有 Reactive Extension 的 ReactiveList 中键入了一个词

Verify if a user typed a word from a ReactiveList with Reactive Extension

我有一个带有关键字的 ReactiveList。用户可以从该列表中添加或删除关键字。该应用程序需要验证用户是否键入了其中一个关键字。 已经有一个类似的 post 但它没有考虑到灵活的列表: 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,但我会失去所有订阅。 那么,我怎样才能得到一个 Observable 字符串呢?

首先,MaxAny 都有重载,分别接受一个选择器和一个谓词。这否定了 Select.

的需要

接下来,我将 Observable.Merge 更改为使用 ReactiveListChanged 属性,这是 INotifyCollectionChanged 的 Rx 版本。我还更改了 Select 以生成 intIEnumerable;只是感觉更正确™。

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 个字符。为 combo
  2. 的每个可能长度创建这样一个可观察对象
  3. IEnumerable<IObservable<string>> 中的 observables 合并为一个 Observable<string>
  4. 只让 KeyTrigger 之一的字符串通过
  5. 由于 rangeToMax.Select 生成 IObservable<IObservable<string>> 我们使用 Switch 仅订阅 IObservable<IObservable<string>> 生成的最新 IObservable<string>