3

我试图理解为什么以下代码有效(取自http://jyliao.blogspot.com/2007/10/learning-wpf.html):

open System
open System.Windows
open System.Windows.Input

(* From Chap 1 - HandleAnEvent.cs *)
let WindowOnMouseDown sender (args:MouseButtonEventArgs) =
   let win = unbox<Window> sender
   let str = sprintf "Window clicked with %A button at point (%A)" args.ChangedButton (args.GetPosition win)
   MessageBox.Show(str)|>ignore

let win = new Window()
win.Title <- "Handle an Event"
win.add_MouseDown(new MouseButtonEventHandler(WindowOnMouseDown))

#if COMPILED
[<STAThread()>]
do 
    let app =  new Application() in
    app.Run(win) |> ignore
#endif

我不明白的部分是对add_MouseDown. 当我将鼠标悬停在 VS 中的调用上时,它告诉我该方法来自 UIElement 类,但我在 .NET 类库中找不到对该方法的任何引用。

在 F# 中,我希望调用是:

win.MouseDown.AddHandler (new MouseButtonEventHandler(WindowOnMouseDown))

当我进行此更改时,弹出的消息框不再显示您单击的窗口内的坐标。相反,它显示的坐标与窗口内鼠标单击的位置无关,但随着您在屏幕上移动窗口而改变。因此,该参数似乎sender指的是窗口以外的某些 UI 元素。

有谁明白为什么使用 add_MouseDown 有效(以及该方法的存在记录在哪里),以及为什么使用 AddHandler 不起作用?

我正在使用 VS2010、F# 2.0、.NET 3.0 库。

更新:

啊,我刚刚意识到我错了,使用 AddHandler 与使用 add_MouseDown 的工作方式不同。我实际上一直在做的是使用两种不同的方法一个接一个地添加两个事件处理程序:

win.add_MouseDown(new MouseButtonEventHandler(WindowOnMouseDown))
win.MouseDown.AddHandler (new MouseButtonEventHandler(WindowOnMouseDown))

这会弹出两个消息窗口,第一个显示窗口内的正确位置,第二个显示另一个愚蠢的位置。但是,如果我真的将 add_MouseDown 调用替换为 addHandler 调用,那么我会得到相同的结果。

所以对于这一部分,我认为我真正的问题是为什么第二个事件处理程序报告不同的位置。但也许这最好作为一个单独的问题来处理。

4

2 回答 2

2

我不确定为什么它不起作用,但是您可以通过将闭包传递给来完成同样的事情Add

let win = Window()
win.MouseDown.Add(fun args ->
  let str = sprintf "Window clicked with %O button at point (%O)" args.ChangedButton (args.GetPosition(win))
  MessageBox.Show(str) |> ignore)

现在很清楚win指的是什么(并且不需要拆箱)。sender无论如何,这比无类型参数要好。也许它会按预期工作?

于 2012-09-14T22:29:36.190 回答
0

add_MouseDown是事件的添加访问器的名称MouseDown
在 C# 中,此方法通过编写win.MouseDown += ....
在 VB.Net 中,它被称为AddHandler(win, AddressOf ...).

F# 没有用于添加事件处理程序的特殊语法,因此您需要显式调用它。

于 2012-09-14T22:09:45.157 回答