在 Windows Phone 8 中具有按钮点击并按住事件的 Rx
本文关键字:事件 Rx 按钮 Phone Windows | 更新日期: 2023-09-27 18:21:57
我有一个简单的Windows Phone 8应用程序,带有一个按钮和一个文本框。如何将反应式扩展用于按钮点击并按住事件以更改文本框文本?
void AttachRx()
{
IScheduler cs = new DispatcherScheduler(Deployment.Current.Dispatcher);
Observable.FromEvent<System.Windows.Input.KeyEventArgs>(btn, "Tap").Throttle(TimeSpan.FromSeconds(.5), cs)
.Do(a => ChangeText()).Subscribe();
}
错误信息:
{System.InvalidOperationException:事件委托的形式必须是 void Handler(object, T(,其中 T : EventArgs。 at Microsoft.Phone.Reactive.Observable.FromEvent[TEventArgs](Object target, String eventName( at PhoneApp4.MainPage.AttachRx(( 在PhoneApp4.MainPage..ctor((}
这里有几个问题需要解决。
您报告的错误特别指出您尝试添加到 Tap 事件的委托不兼容 - 这是有道理的,因为我不认为 Tap
事件的有效负载KeyEventArgs
(我认为它是GestureEventArgs
(?您可能最好使用下面示例中使用的Observable.FromEventPattern
。这更容易,因为您可以推断EventArgs
类型。
警告 - 由于我目前笔记本电脑上只有 WP8.1 SDK,所以我只有与 Tap
不同的 Win RT Tapped
事件,所以我刚刚阅读了Tap
上的文档,而不是运行下面的示例。
假设一个名为 btn
的Button
和一个名为 txt 的TextBox
以及获取要设置的文本的函数string GetText()
,请执行以下操作:
Observable.FromEventPattern<GestureEventArgs>(btn, "Tap")
.Throttle(TimeSpan.FromSeconds(0.5))
.Select(_ => GetText())
.ObserveOnDispatcher()
.Subscribe(x => this.txt.Text = x);
请注意以下几点:
- 当标准 .NET 事件可用时,请使用
FromEventPattern
- 它更适合于此FromEvent
真正存在以处理不符合委托。 - 不要像这样使用
Do
。它作为一个副作用,并不是真正的惯用函数式反应式编程。这样做通常还可能导致更复杂的查询中出现意外问题。相反,使用Select
将输入事件投影到所需的结果。 - 不要在调度程序上运行
Throttle
- 使用默认调度程序(或使用.Throttle(TimeSpan.FromSeconds(0.5), Scheduler.Default)
参数化可测试性。您不需要在调度程序上运行 Throttle - 最好在后台运行。您只想在准备好更新 UI 时转移到调度程序。 - 如果导入 nuget 包
rx-xaml
则可以使用ObservableOnDispatcher
获取当前调度程序。虽然,为了可测试性,您可能希望使用ObserveOn
的重载(也在 rx-xaml 中(,它采用依赖对象,例如您正在运行的页面 - 例如ObserveOn(this)
例如,如果您在页面代码隐藏中设置订阅,页面本身就可以了。
上面的示例假定GetText
是同步的。如果需要进行异步调用以获取要显示的文本,请使用以下模式(假设GetText
具有Task<String>
返回类型(:
Observable.FromEventPattern<GestureEventArgs>(btn, "Tap")
.Throttle(TimeSpan.FromSeconds(0.5), Scheduler.Default)
.Select(_ => Observable.FromAsync(GetText)
.ObserveOn(this))
.Switch()
.Subscribe(x => this.Name.Text = x);
请注意ObserveOn
在Select
内看起来很奇怪。简要解释其原因非常复杂(我不确定它与这个问题的相关性如何(,但基本上它避免了竞争条件,即如果对较早事件的长时间运行的异步 GetText 调用可能会由于稍后的事件而覆盖短运行调用的结果。