[英]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.