![](/img/trans.png)
[英]How to Create Asynchronous HttpWebRequest in Silverlight( F#)
[英]Drag and Drop in Silverlight with F# and Asynchronous Workflows
我正在嘗試使用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())
()
非常感謝您的寶貴時間!
解決此問題的方法是使用重載的AwaitEvent
,它允許您等待兩個事件。 而不是只是等待MouseMove
,你也可以等待MouseUp
事件 - 在第一種情況下,你可以繼續移動,在第二種情況下,你可以從循環返回並停止拖放(這實際上將在本書的后面討論)第16.4.5節)。
這是代碼 - 它實際上使用方法的AwaitObservable
變體(見下文),這是一個更好的選擇,因為它適用於Observable.map
和類似的組合器(如果你想使用它們)。
let! args = Async.AwaitObservable(layoutRoot.MouseMove, layoutRoot.MouseUp)
match args with
| Choice1Of2(args) ->
// Handle the 'MouseMove' event with 'args' here
Canvas.SetLeft(rectangle1, args.GetPosition(layoutRoot).X)
Canvas.SetTop(rectangle1, args.GetPosition(layoutRoot).Y)
return! drag()
| Choice2Of2(_) ->
// Handle the 'MouseUp' event here
return()
據我所知,重載的AwaitObservable
方法在F#庫中尚未提供,但您可以從本書的網站上獲取它,或者您可以使用以下代碼:
// Adds 'AwaitObservable' that takes two observables and returns
// Choice<'a, 'b> containing either Choice1Of2 or Choice2Of2 depending
// on which of the observables occurred first
type Microsoft.FSharp.Control.Async with
static member AwaitObservable(ev1:IObservable<'a>, ev2:IObservable<'b>) =
Async.FromContinuations((fun (cont,econt,ccont) ->
let rec callback1 = (fun value ->
remover1.Dispose()
remover2.Dispose()
cont(Choice1Of2(value)) )
and callback2 = (fun value ->
remover1.Dispose()
remover2.Dispose()
cont(Choice2Of2(value)) )
// Attach handlers to both observables
and remover1 : IDisposable = ev1.Subscribe(callback1)
and remover2 : IDisposable = ev2.Subscribe(callback2)
() ))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.