反应式扩展的可观察模式

Observable pattern on reactive extension

我试图理解下面尝试使用响应式扩展的代码

 IObservable<string> textChangedObservable =
            Observable.FromEventPattern<TextChangedEventArgs>(searchScrip, "TextChanged")
                .Select(evt => ((TextBox) sender).Text);

 textChangedObservable.Subscribe(OnNext, OnCompleted);

private void OnNext(string s)
    {
        System.Diagnostics.Debug.Print("OnNext " + s + "\n");
    }

    private void OnCompleted()
    {
        System.Diagnostics.Debug.Print("OnCompleted " + "\n");
    }

如果我在输入框中输入 SEARC,输出看起来

可能是因为您使用了 RoutedPropertyChangedEventArgs?

如果使用 PropertyChangedEventHandler 会怎样?

Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                h => yourModel.propertyChanged += h,
                h => yourModel.propertyChanged -= h)
            .Where(x => x.EventArgs.PropertyName = "your_property_name");
    }

这里的问题确实与Rx无关

1: Why is "S" not triggering an OnNext?

因为您订阅的 TextChanged 事件没有在第一个 S 上触发。

2: Why is OnCompleted never called?

当您将 .NET 事件包装为 IObservable<T> 时,您永远不会收到 OnErrorOnCompleted 通知。 .NET 事件没有错误或完成的概念。

如果有两个个事件,一个用于值,一个用于完成,您可以像这样组合它们:

var values = Observable.FromEvent(...);
var completion = Observable.FromEvent(...);
var query = values.TakeUntil(completion);

现在 query 将产生适当的 OnCompleted 通知。

3: Why is the OnNext called n-1 time on the nth character?

因为您订阅的 TextChanged 事件以这种方式触发。正如@Kari-Antti 所指出的,这可能是使用 "routed property" 事件的副作用。

看来您正在订阅 searchScrip_TextChanged 处理程序中的可观察对象。

这意味着 searchScrip_TextChanged 第一次被调用 S 已经发生 您已经连接了可观察对象之前。所以当然不会火

但是现在 S 被击中了,你有一个订阅,所以当输入 E 时,你会得到一个 SE。但是由于 searchScrip_TextChanged 处理程序也被调用为 E 你现在有两个对你的 observable 的订阅。

因此,当输入 A 时,您会得到两个 SEA,因为您有两个可观察值。但是再次为 A 调用 searchScrip_TextChanged 所以现在你有三个可观察值。

等等等等

活动不会自动完成。您需要手动处理订阅才能结束订阅。这应该是有道理的,因为这就是您要停止的普通事件处理程序所要做的。

您应该在加载表单时创建可观察对象,以便只创建一次。

它应该是这样的:

IObservable<string> textChangedObservable =
        Observable.FromEventPattern<TextChangedEventArgs>(searchScrip, "TextChanged")
            .Select(evt => searchScrip.Text);

IDisposable subscription =
    textChangedObservable
        .Subscribe(
            s => Debug.Print("OnNext " + s + "\n"),
            s => Debug.Print("OnCompleted\n"));