簡體   English   中英

F#WPF異步命令完成狀態

[英]F# wpf async command completion status

我一直在嘗試使用F#Viewmodule異步命令。 問題是當我單擊按鈕時,命令將被執行,但是此后按鈕保持禁用狀態。

XAML:

<Button Content="start async worker" Command="{Binding StartAsyncCommand}" />

視圖模型:

type MainViewModel() as me = 
  inherit ViewModelBase()
//...
member __.StartAsyncCommand = me.Factory.CommandAsync(fun _ -> async { return () } )

我究竟做錯了什么?

編輯:

感謝@FoggyFinder,我們確定問題實際上出在App.fs文件中:

open System
open FsXaml
open System.Windows

type MainWindow = XAML< "MainWindow.xaml">

[<STAThread>]
[<EntryPoint>]
let main argv = 
  Application().Run(MainWindow().Root)

創建基本上空的App.xaml並開始如下操作:

module main

open System
open FsXaml

type App = XAML<"App.xaml">

[<STAThread>]
[<EntryPoint>]
let main argv =
    App().Root.Run()

修復。 如果有人知道這方面的解釋,請隨時提供。

我使用了異步命令,但從未出現此問題。 我試圖重現您的代碼-一切正常。 您確定輸入了完整的代碼嗎?

嘗試運行代碼:.xaml:

<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>
<Grid>
    <Button Content="start async worker" Command="{Binding StartAsyncCommand}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5" />
    <TextBlock Text="{Binding Count}" Margin="5" HorizontalAlignment="Right"  VerticalAlignment="Top"></TextBlock>
</Grid>

視圖模型:

type MainViewModel() as me = 
    inherit ViewModelBase()    

    let count = me.Factory.Backing(<@ me.Count @>, 0)

    member __.StartAsyncCommand = me.Factory.CommandAsync(fun _ -> async { count.Value <- count.Value + 1 })
    member __.Count with get() = count.Value

關於之間的區別

let dosomething _ = async { return () }
member __.StartAsyncCommand = me.Factory.CommandAsync(dosomething)

和:

member __.StartAsyncCommand = me.Factory.CommandAsync(fun _ -> async { return () } )

看看這個答案: http : //chat.stackoverflow.com/transcript/message/26511092#26511092

我究竟做錯了什么?

問題在於,在構造ViewModel層時沒有適當的SynchronizationContext,這意味着將內容推回UI上下文的內部代碼無法正常工作。

您可以在調用Application.Run()之前,在入口點的開頭添加以下內容來解決此問題:

if SynchronizationContext.Current = null then
    DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher)
    |> SynchronizationContext.SetSynchronizationContext

這將確保已創建Dispatcher並安裝了有效的SynchronizationContext ,並且可能會為您解決問題。

一種簡單的解決方法是使用交互觸發器:

<Button>
    <ia:Interaction.Triggers>
        <ia:EventTrigger EventName="Click">
            <fsx:EventToCommand Command="{Binding StartAsyncCommand}" />
        </ia:EventTrigger>
    </ia:Interaction.Triggers>
</Button>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM