Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何转换WPF按钮。使用Rx和F将事件单击为可观察事件#_Wpf_F#_System.reactive_Routedevent - Fatal编程技术网

如何转换WPF按钮。使用Rx和F将事件单击为可观察事件#

如何转换WPF按钮。使用Rx和F将事件单击为可观察事件#,wpf,f#,system.reactive,routedevent,Wpf,F#,System.reactive,Routedevent,我试图复制一些C代码,该代码从按钮创建一个IObservable。单击事件。 我想将此代码移植到F# 以下是编译时没有错误的原始C#代码: Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>( h => new RoutedEventHandler(h), h =>

我试图复制一些C代码,该代码从
按钮创建一个
IObservable
。单击事件。 我想将此代码移植到F#

以下是编译时没有错误的原始C#代码:

Observable.FromEvent<RoutedEventHandler, RoutedEventArgs>(
                                    h => new RoutedEventHandler(h),
                                    h => btn.Click += h,
                                    h => btn.Click -= h))
Observable.FromEvent(
h=>新的路由EventHandler(h),
h=>btn。单击+=h,
h=>btn。单击-=h)
以下是我在F#中尝试同样方法的失败:

Observable.FromEvent(
Func(乐趣h->RoutedEventHandler(h)),
操作(乐趣h->btn.Click.AddHandler h),
操作(乐趣h->btn.Click.RemoveHandler)
除了声明的第二行,一切都很愉快

F#编译器抱怨
fun h->RoutedEventHandler(h)
,因为 它不想将
h
作为
RoutedEventHandler
构造函数的参数

另一方面,C#编译器似乎在接受新的RoutedEventHandler(h)

有趣的是,在两个代码示例(C和F)中,
h
的类型都是
EventHandler

我从F#编译器得到的错误消息是:

错误2此表达式应具有类型obj->RoutedEventTargets->unit,但此处具有类型EventHandler

我在PresentationCore中找到的
RoutedEventHandler
的签名是:

public委托void RoutedEventHandler(对象发送方,RoutedEventArgs e)

正如您所见,它确实将
对象
路由目标
作为参数,因此F#编译器实际上是正确的

C#编译器在幕后是否有一些魔力,使F#编译器无法完成这项工作,还是我在这里遗漏了什么


无论是哪种方式,我如何在F#中实现此功能?

这是我所知道的从WPF按钮中生成
IObservable
的最简单方法。单击事件将强制执行它:

open System
open System.Windows.Controls

let btn = new Button()
let obsClick = btn.Click :> IObservable<_>
开放系统
打开System.Windows.Controls
设btn=新建按钮()
让obsClick=btn。单击:>IObservable
正在检查单击

val obsClick : IObservable<Windows.RoutedEventArgs>
val observable单击:ioobservable

这是可能的,因为标准.NET事件的F#表示是类型(在本例中)
IEvent
。正如您可以从文档中看到的那样。换句话说,在F#中,每一个事件都已经是一个可观察的

乔尔·穆勒(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)
)
谢谢,通过查看Reflector中的C#代码,我意识到“h”实际上被扩展为“h.Invoke”,然后被视为表示“(s,e)=>h.Invoke(s,e)”的方法组,从而满足RoutedEventHandler签名。一旦清楚了这一点,很明显,你所建议的F#实现在金钱上是正确的。不过,我也同意Joel Mueller建议的不太详细的转换是首选,除非您需要直接获得发送方的联系(例如,不通过args.Source),因为它只返回RoutedEventTargets的IObservable。
Observable.FromEvent(
    (fun h -> RoutedEventHandler(fun sender e -> h.Invoke(sender, e))),
    (fun h -> b.Click.AddHandler h),
    (fun h -> b.Click.RemoveHandler h)
)