结合WPF中的事件和F#(或者,我疯了吗?)

时间:2011-04-26 11:22:23

标签: wpf events f#

玩穗,我正试图拖动WPF标签。我从here翻译了Don Syme的mkMouseTracker代码,它看起来应该有效,但出于某种原因,从mouseEvent返回的两个args之间从来没有任何区别,所以我的标签从不动。

printf似乎表明last参数被moveArgs中的值吞噬/替换。这与使用ref吗?

有关

对不起,代码块有点长,但它是自包含的。

#r "WindowsBase"
#r "PresentationCore"
#r "PresentationFramework"
#r "System.Xaml"

open System
open System.Windows
open System.Windows.Media
open System.Windows.Controls

let window = new Window(Name="Test",Width=500.0,Height=500.0)
window.Visibility <- Visibility.Visible
window.Show()

let l = new System.Windows.Controls.Label(Height = 30., Width = 150., 
            BorderBrush = Brushes.Black, BorderThickness = Thickness(3.))
window.Content <- l

let mkMouseTracker (c : #UIElement) =
  let event = new Event<_>()
  let lastArgs = ref None
  c.MouseDown.Add(fun args -> lastArgs := Some (args :> Input.MouseEventArgs ))
  c.MouseUp  .Add(fun args -> lastArgs := None)
  c.MouseMove.Add(fun moveArgs ->
    match !lastArgs with
    | Some last -> event.Trigger(last,moveArgs); lastArgs := Some moveArgs
    | None -> ())
  event.Publish

let mouseEvent = mkMouseTracker l
mouseEvent.Add(fun (args1, args2) ->
    let pos1, pos2 = args1.GetPosition(l), args2.GetPosition(l)
    l.RenderTransform <- TranslateTransform(pos2.X - pos1.X, pos2.Y - pos1.Y)
    l.Content <- sprintf "%A: %A -> %A" args1.Timestamp pos1 pos2)

1 个答案:

答案 0 :(得分:3)

我认为您需要在事件触发后立即获取事件的位置。很可能WPF正在为所有事件(或类似事件)重用可变MouseEventArgs对象,因此稍后调用GetPosition会给你相同的点。

以下代码执行某事。它不能完全运行 - 标签被移动到错误的位置,所以它仍然需要修复,但它应该让你开始: - )。

let mkMouseTracker (e : #UIElement) =
  let event = new Event<_>()
  let lastArgs = ref None
  e.MouseDown.Add(fun args -> lastArgs := Some(args.GetPosition(e)))
  e.MouseUp  .Add(fun args -> lastArgs := None)
  e.MouseMove.Add(fun moveArgs ->
    match !lastArgs with
    | Some last -> 
        let pos = moveArgs.GetPosition(e)
        event.Trigger(last,pos)
        lastArgs := Some pos
    | None -> ())
  event.Publish

let mouseEvent = mkMouseTracker l
mouseEvent.Add(fun (pos1, pos2) ->
    l.RenderTransform <- TranslateTransform(pos2.X - pos1.X, pos2.Y - pos1.Y)
    l.Content <- sprintf "%A" (pos2.X - pos1.X, pos2.Y - pos1.Y))