我試圖在使用F#和異步工作流的Silverlight中實現拖放操作。使用F#和異步工作流在Silverlight中拖放
我只是試圖在畫布上拖動一個矩形,使用兩個狀態(等待和拖動)的兩個循環,這是我從Tomas Petricek的書「Real-world Functional Programming」得到的一個想法,但是我遇到問題:
與WPF或WinForms不同,Silverlight的MouseEventArgs不包含關於按鈕狀態的信息,所以我不能通過檢查鼠標左鍵是否被按下而從拖動循環返回。我只設法通過引入一個可變的標誌來解決這個問題。
有沒有人有解決方案,這不涉及可變狀態?
下面是相關的代碼部分(請原諒馬虎拖拉代碼,它捕捉矩形鼠標指針):
type MainPage() as this =
inherit UserControl()
do
Application.LoadComponent(this, new System.Uri("/SilverlightApplication1;component/Page.xaml", System.UriKind.Relative))
let layoutRoot : Canvas = downcast this.FindName("LayoutRoot")
let rectangle1 : Rectangle = downcast this.FindName("Rectangle1")
let mutable isDragged = false
do
rectangle1.MouseLeftButtonUp.Add(fun _ -> isDragged <- false)
let rec drag() = async {
let! args = layoutRoot.MouseMove |> Async.AwaitEvent
if (isDragged) then
Canvas.SetLeft(rectangle1, args.GetPosition(layoutRoot).X)
Canvas.SetTop(rectangle1, args.GetPosition(layoutRoot).Y)
return! drag()
else
return()
}
let wait() = async {
while true do
let! args = Async.AwaitEvent rectangle1.MouseLeftButtonDown
isDragged <- true
do! drag()
}
Async.StartImmediate(wait())
()
非常感謝您的寶貴時間!
非常感謝您提供快速而徹底的答案,Tomas。我想知道爲什麼你在書中使用了AwaitObservable而不是AwaitEvent,因爲我認爲你沒有在書中討論這個。無論如何,我現在明白了 - 再次感謝! – knotig 2010-06-06 20:58:46
@ knotig:「AwaitEvent」的問題在於,如果您將它與例如'Event.map',你得到一個內存泄漏。 'Observable'版本不會遇到這個問題。我更詳細地寫了這篇文章 - 我建議一種修復F#事件的方法(除了使用Observables之外),但是如果您對技術細節感興趣,也可以相對清楚地解釋這個問題:http:// tomasp .NET /學術/事件鏈/事件chains.pdf – 2010-06-07 04:03:33