我有一个简单的Windows Phone 8应用程序,带有按钮和文本框。如何使用Reactive Extensions按钮点击并按住事件来更改TextBox文本?
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) 在PhoneApp4.MainPage.AttachRx() 在PhoneApp4.MainPage..ctor()}
答案 0 :(得分:1)
这里有几个问题要解决。
您报告的错误明确指出您尝试添加到Tap事件的代理不兼容 - 这是有道理的,因为我不认为Tap
事件有{{1}有效载荷(我认为它是KeyEventArgs
)?你也可能最好使用我在下面的例子中使用的GestureEventArgs
。这可以更容易,因为你可以推断出Observable.FromEventPattern
类型。
警告 - 由于目前我的笔记本电脑上只有WP8.1 SDK,因此我只有Win EventArgs
事件与Tapped
不同,所以我刚刚阅读了Tap
上的文档而没有运行下面的示例。
假设名为Tap
的{{1}}和名为txt的Button
以及要设置文本的函数btn
,请执行以下操作:
TextBox
请注意以下几点:
string GetText()
- 它比Observable.FromEventPattern<GestureEventArgs>(btn, "Tap")
.Throttle(TimeSpan.FromSeconds(0.5))
.Select(_ => GetText())
.ObserveOnDispatcher()
.Subscribe(x => this.txt.Text = x);
更适合这种情况,而FromEventPattern
确实存在以处理不合规代表。FromEvent
。它起到副作用的作用,并不是真正的惯用功能反应式编程。这样做通常也可能导致更复杂的查询出现意外问题。而是使用Do
将输入事件投影到所需的结果。Select
- 使用默认调度程序(或使用Throttle
参数化可测试性。您不需要在调度程序上运行Throttle - 它最好在您只想在准备好更新UI时转移到调度程序。.Throttle(TimeSpan.FromSeconds(0.5), Scheduler.Default)
,则可以使用rx-xaml
来获取当前的调度程序。虽然为了可测试性,您可能希望使用ObservableOnDispatcher
(也在rx-xaml中)的重载,该重载采用依赖对象,例如您正在运行的页面 - 例如ObserveOn
如果您在页面代码隐藏中设置订阅,例如页面本身就可以。上面的示例假设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
的奇怪展示位置。简单解释这个原因是非常复杂的(我不确定它与这个问题有多相关),但基本上它避免了竞争条件,如果对早期事件的长时间运行异步GetText调用可能会覆盖由于后来的事件导致短暂的通话结果。