验证用户是否从带有 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 字符串呢?
首先,Max
和 Any
都有重载,分别接受一个选择器和一个谓词。这否定了 Select
.
的需要
接下来,我将 Observable.Merge
更改为使用 ReactiveList
的 Changed
属性,这是 INotifyCollectionChanged
的 Rx 版本。我还更改了 Select
以生成 int
的 IEnumerable
;只是感觉更正确™。
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
- 创建一个
IObservable<string>
发出用户输入的最后 n
个字符。为 combo 的每个可能长度创建这样一个可观察对象
- 将
IEnumerable<IObservable<string>>
中的 observables 合并为一个 Observable<string>
- 只让
KeyTrigger
之一的字符串通过
- 由于
rangeToMax.Select
生成 IObservable<IObservable<string>>
我们使用 Switch
仅订阅 IObservable<IObservable<string>>
生成的最新 IObservable<string>
。
我有一个带有关键字的 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 字符串呢?
首先,Max
和 Any
都有重载,分别接受一个选择器和一个谓词。这否定了 Select
.
接下来,我将 Observable.Merge
更改为使用 ReactiveList
的 Changed
属性,这是 INotifyCollectionChanged
的 Rx 版本。我还更改了 Select
以生成 int
的 IEnumerable
;只是感觉更正确™。
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
- 创建一个
IObservable<string>
发出用户输入的最后n
个字符。为 combo 的每个可能长度创建这样一个可观察对象
- 将
IEnumerable<IObservable<string>>
中的 observables 合并为一个Observable<string>
- 只让
KeyTrigger
之一的字符串通过 - 由于
rangeToMax.Select
生成IObservable<IObservable<string>>
我们使用Switch
仅订阅IObservable<IObservable<string>>
生成的最新IObservable<string>
。