反应式扩展的可观察模式
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,输出看起来
- OnNext SE
- OnNext SEA
- OnNext SEA
- OnNext SEAR
- OnNext SEAR
- OnNext SEAR
- OnNext SEARC
- OnNext SEARC
- OnNext SEARC
OnNext SEARC
- 为什么 "S" 没有触发 OnNext?
- 为什么从不调用 OnCompleted?
- 为什么OnNext在第n个字符被调用了n-1次?
可能是因为您使用了 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>
时,您永远不会收到 OnError
或 OnCompleted
通知。 .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"));
我试图理解下面尝试使用响应式扩展的代码
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,输出看起来
- OnNext SE
- OnNext SEA
- OnNext SEA
- OnNext SEAR
- OnNext SEAR
- OnNext SEAR
- OnNext SEARC
- OnNext SEARC
- OnNext SEARC
OnNext SEARC
- 为什么 "S" 没有触发 OnNext?
- 为什么从不调用 OnCompleted?
- 为什么OnNext在第n个字符被调用了n-1次?
可能是因为您使用了 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>
时,您永远不会收到 OnError
或 OnCompleted
通知。 .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"));