wpf - 在 WPF 和 F# 中组合事件(或者,我要疯了吗?)

标签 wpf events f#

我尝试使用尖峰来拖动 WPF 标签。我从 here 翻译了 Don Syme 的 mkMouseTracker 代码,它看起来应该可以工作,但由于某种原因,从 mouseEvent 返回的两个 args 之间从来没有任何区别,所以我的标签永远不会移动。

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

最佳答案

我觉得你需要在事件触发后立即获取事件的位置。很可能 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))

关于wpf - 在 WPF 和 F# 中组合事件(或者,我要疯了吗?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5789579/

相关文章:

c# - WPF TabControl 与 ContentControl

python - Sqlalchemy 混合/和事件监听器

.net - 为什么 ObservableForProperty 上的 ReactiveUI 的 ToProperty 会导致 F# 中的 FailInit

wpf - 在WPF中在 View / View 模型之间进行转换的可重用/很好的方式而无需任何代码隐藏

wpf - 在网格 WPF 中对齐标签

jquery - 如果用户光标在我的元素上停留几秒钟,则调用鼠标悬停

javascript - 如果jquery live event代码已被删除,我还需要解绑它吗?

F# 函数,其中 x 可以被 2 或 3 整除,但不能被 5 整除

f# - 在 F# 中创建类型的不可比较版本

c# - 无法将类型 'System.String' 的对象强制转换为 "..Controls.SurfaceListBoxItem' 异常