2011-04-26 37 views
3

玩秒殺,我試圖拖動一個WPF標籤。我翻譯了Don Syme的mkMouseTracker代碼here,它看起來應該可以工作,但由於某種原因,從mouseEvent返回的兩個參數之間沒有任何區別,所以我的標籤從不移動。在WPF和F#中組合事件(或者,我會瘋了嗎?)

printf ing似乎表明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) 

回答

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)) 
+0

滴答「因爲它的答案,和+1」因爲這意味着我*不*瘋狂:) – Benjol 2011-04-26 12:26:44

+2

ILSpy說,爲getPosition內部進行呼叫直接向MouseDevice沒有采摘當前座標。由於MouseDevice在事件參數的兩個實例中可能都是相同的,因此這解釋了當前的行爲。 – desco 2011-04-26 12:59:05