Tho*_*enz 14 wpf f# routedevent system.reactive
我试图复制一些C#代码,它创建IObservable一个Button.Click事件.我想将此代码移植到F#.
这是原始的C#代码,它编译时没有错误:
Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
                                    h => new RoutedEventHandler(h),
                                    h => btn.Click += h,
                                    h => btn.Click -= h))
这是我在F#中做同样失败的尝试:
Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
            Func<EventHandler<RoutedEventArgs>, RoutedEventHandler>(fun h -> RoutedEventHandler(h)),
            Action<RoutedEventHandler>(fun h -> btn.Click.AddHandler h),
            Action<RoutedEventHandler>(fun h -> btn.Click.RemoveHandler h))
除了声明的第二行,一切都很愉快.
F#编译器抱怨,fun h -> RoutedEventHandler(h)因为它不希望除了h作为RoutedEventHandler构造函数的参数.
另一方面,C#编译器似乎没有接受的问题 h => new RoutedEventHandler(h)
有趣的是,在两个代码示例(C#和F#)中,类型h都是EventHandler<RoutedEventArgs>.
我从F#编译器获取的错误消息是:
错误2此表达式应该具有类型obj - > RoutedEventArgs - > unit但这里有类型EventHandler
RoutedEventHandler我在PresentationCore中找到的签名是:
public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);
正如您所看到的,它确实需要一个object和RoutedEventArgs作为参数,因此F#编译器实际上是正确的.
是否有一些魔术,C#编译器在幕后做了F#编译器没有的工作,或者我在这里错过了什么?
无论哪种方式,我怎样才能在F#中完成这项工作?
Joe*_*ler 17
我知道的最简单的方法IObservable<_>是使用WPF Button.Click事件来构建它:
open System
open System.Windows.Controls
let btn = new Button()
let obsClick = btn.Click :> IObservable<_>
检查obsClick ...
val obsClick : IObservable<Windows.RoutedEventArgs>
这是可能的,因为标准.NET事件的F#表示是类型(在本例中)IEvent<Windows.RoutedEventHandler,Windows.RoutedEventArgs>.从文档中可以看出,IEvent实现了IObservable.换句话说,在F#中,每个事件都已经是一个IObservable.
Joel Mueller很有见,所以只是为了记录:直接翻译C#代码
Observable.FromEvent(
    (fun h -> RoutedEventHandler(fun sender e -> h.Invoke(sender, e))),
    (fun h -> b.Click.AddHandler h),
    (fun h -> b.Click.RemoveHandler h)
)
| 归档时间: | 
 | 
| 查看次数: | 2170 次 | 
| 最近记录: |