Xamarin.forms Xamarin表单:点击事件Args派生类型

Xamarin.forms Xamarin表单:点击事件Args派生类型,xamarin.forms,f#,Xamarin.forms,F#,我有一些这样的代码可以很好地工作: type App() = inherit Application() let stack = StackLayout(VerticalOptions = LayoutOptions.Center) let label = Label(XAlign = TextAlignment.Center, Text = "Welcome to F# Xamarin.Forms!") do let tapRecognize

我有一些这样的代码可以很好地工作:

type App() =
    inherit Application()

    let stack = StackLayout(VerticalOptions = LayoutOptions.Center)
    let label = Label(XAlign = TextAlignment.Center, Text = "Welcome to F# Xamarin.Forms!")

    do
        let tapRecognizer = new TapGestureRecognizer()
        let handleTapEvent (sender:Object) (args:EventArgs) =
            label.Text <- "Tapped at " + DateTime.Now.ToString() 
            ()

        let tapEventHandler = new EventHandler(handleTapEvent)
        tapRecognizer.Tapped.AddHandler(tapEventHandler)
        label.GestureRecognizers.Add(tapRecognizer)
type App()=
继承应用程序()
让堆栈=堆栈布局(垂直选项=布局选项.Center)
让label=label(XAlign=TextAlignment.Center,Text=“欢迎使用F#Xamarin.Forms!”)
做
让tapRecognizer=新建TapGestureRecognizer()
let handleTapEvent(发送方:对象)(args:EventArgs)=
label.TextF#不会像C#那样自动插入下拉列表(这是一件好事,不是一个bug)。不能传递预期为祖先类型的子类型

为了调用
AddHandler
,您需要使用downcast操作符
:>
手动插入downcast,如下所示:

type TapEventArgs(someId:int) = 
          inherit EventArgs()
          member this.SomeId = someId

        let handleTapEvent (sender:Object) (args:TapEventArgs) =
            label.Text <- args.SomeId.ToString() + " tapped"
            ()
let tapEventHandler = new EventHandler<TapEventArgs>(handleTapEvent)
tapRecognizer.Tapped.AddHandler(tapEventHandler :> EventHandler<EventArgs>)

这里的问题是类型不同,这就是F#告诉你的。
tap识别器.Tapped
的类型为
EventHandler
,因此当调用它时,它将为
EventHandler
类型,即不是
EventHandler
,这是一种不同的类型。无法更改这一点,而且由于类是密封的,因此不可能对
TapGestureRecognitor
进行子类化

此外,您发布的代码将很难编译,因为它具有循环引用,这是F#所阻止的
TapEventArgs
需要
标签
,该标签在
应用程序中定义<代码>应用程序
取决于
TapEventArgs
。无法从
TapEventArgs
更新UI,而是需要传入函数,或者暴露状态

有一种使用
命令
模式的解决方案,它允许将一些信息传递给回调,并避免循环依赖
TapGestureRecognitor
有一个属性
CommandParameter
,其中可以设置值(obj类型)。可以通过可接收该值的
命令
属性提供回调。以下是完整的示例:

open Xamarin.Forms
open System

type App() as this =
    inherit Application()

    let stack = StackLayout(VerticalOptions = LayoutOptions.Center)
    let label = Label(XAlign = TextAlignment.Center, Text = "Welcome to F# Xamarin.Forms!")

    do
        let tapRecognizer = new TapGestureRecognizer()
        let handleTapEvent (x:obj) = 
            match x with 
            | :? int as someId -> label.Text <- someId.ToString() + " tapped"
            | _ -> label.Text <- "Tapped at " + DateTime.Now.ToString() 

        tapRecognizer.Command <- new Command(Action<obj>(fun x -> handleTapEvent x))
        label.GestureRecognizers.Add(tapRecognizer)
        stack.Children.Add label

        tapRecognizer.CommandParameter <- 42 // The value to be passed to the Command's callback
        this.MainPage <- ContentPage(Content = stack)
打开Xamarin.Forms
开放系统
键入App(),如下所示=
继承应用程序()
让堆栈=堆栈布局(垂直选项=布局选项.Center)
让label=label(XAlign=TextAlignment.Center,Text=“欢迎使用F#Xamarin.Forms!”)
做
让tapRecognizer=新建TapGestureRecognizer()
让handleTapEvent(x:obj)=
将x与

| :? int as someId->label.Text label.Text在AddHandler方法中添加向下转换不起作用。tapRecognizer.Tapped.AddHandler(tapEventHandler:>EventHandler)抛出此表达式应具有类型“EventHandler”,但此处具有类型“EventHandler”
tapRecognizer.Tapped的类型是什么?
tapRecognizer.Tapped.AddHandler(tapEventHandler :> _)
open Xamarin.Forms
open System

type App() as this =
    inherit Application()

    let stack = StackLayout(VerticalOptions = LayoutOptions.Center)
    let label = Label(XAlign = TextAlignment.Center, Text = "Welcome to F# Xamarin.Forms!")

    do
        let tapRecognizer = new TapGestureRecognizer()
        let handleTapEvent (x:obj) = 
            match x with 
            | :? int as someId -> label.Text <- someId.ToString() + " tapped"
            | _ -> label.Text <- "Tapped at " + DateTime.Now.ToString() 

        tapRecognizer.Command <- new Command(Action<obj>(fun x -> handleTapEvent x))
        label.GestureRecognizers.Add(tapRecognizer)
        stack.Children.Add label

        tapRecognizer.CommandParameter <- 42 // The value to be passed to the Command's callback
        this.MainPage <- ContentPage(Content = stack)