我一直在使用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()
修好了。如果有人知道对此的解释,请不要犹豫,提供它。
答案 0 :(得分:2)
我使用了异步命令,但这个问题从未出现过。我试图重现你的代码 - 一切正常。你确定你提供了完整的代码吗?
尝试运行代码: 的.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
答案 1 :(得分:2)
我做错了什么?
问题是构建ViewModel层时没有SynchronizationContext,这意味着将内容推回到UI上下文的内部代码无法正常工作。
您可以在致电Application.Run()
之前在入口点的开头添加以下内容来解决此问题:
if SynchronizationContext.Current = null then
DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher)
|> SynchronizationContext.SetSynchronizationContext
这将确保创建Dispatcher
并安装有效的SynchronizationContext
,并且可能会为您解决问题。
答案 2 :(得分:1)
简单的解决方法是使用交互触发器:
<Button>
<ia:Interaction.Triggers>
<ia:EventTrigger EventName="Click">
<fsx:EventToCommand Command="{Binding StartAsyncCommand}" />
</ia:EventTrigger>
</ia:Interaction.Triggers>
</Button>