我的绑定 属性 之一和我的 ActivityIndi​​cator 之间的问题

Problem between one of my binded property and my ActivityIndicator

我在使用 F# 方面还很陌生,我正在尝试用 F# 重写一个完整的 C# 库。我有一个 Xamarin.forms 项目,其中的 C# 库包含我所有的视图,我的目标是拥有另外两个库,一个在 C# 中,一个在 F# 中,每个库都包含相同的 ViewModel。 一切正常,除了我的 属性.

中的最后一件小事

我的应用程序很简单,它只是让用户登录 Facebook,然后检索他在 Facebook Wall 上发布的所有帖子,并使用 ListView 显示这些帖子。在处理检索工作时,我想 运行 一个 ActivityIndi​​cator,以便用户可以看到应用程序正在运行。 这是他的我的 ActivityIndi​​cator 和我的 ListView 在我的 view.xaml :

<ActivityIndicator IsVisible="{Binding IsLoading}" IsRunning="{Binding IsLoading}"
                           VerticalOptions="Center"
                           HorizontalOptions="Center"
                           Grid.Row="0"
                           Grid.Column="0"
                           Scale="4"
                           Color="#0078FF"/>
<ListView x:Name="PostsView"
                          ItemsSource="{Binding PostsDb}"
                          ItemTapped="PostsView_ItemTapped"
                          HasUnevenRows ="True"
                          BackgroundColor="LightGray"
                          IsPullToRefreshEnabled="True"
                          RefreshCommand="{Binding RefreshCommand}"
                          IsRefreshing="{Binding IsRefreshing}"
                          Grid.Row="0"
                          Grid.Column="0"
                          IsVisible="{Binding IsLoading, Converter={StaticResource ReverseBool}}">

这是我的 F# class :

type FacebookViewModel(navigationService: INavigationService) = 
    inherit ViewModelBase()

    let mutable facebookProfile = new FacebookProfileDbObject()
    let mutable postsDb = new List<FacebookPostsDbObject>()
    let mutable isLoading = false

    member this.FacebookProfile
        with get() = facebookProfile 
        and set(value) =
            facebookProfile <- value
            base.NotifyPropertyChanged(<@ this.FacebookProfile @>)

    member this.PostsDb
        with get() = postsDb 
        and set(value) =
            postsDb <- value
            base.NotifyPropertyChanged(<@ this.PostsDb @>)

    member this.IsLoading
        with get() = isLoading 
        and set(value) =
            isLoading <- value
            base.NotifyPropertyChanged(<@ this.IsLoading @>)

    member this.SetData() = 
        this.IsLoading <- true
        this.FacebookProfile <- GetProfileData() |> Async.RunSynchronously
        this.PostsDb <- GetPostData() |> Async.RunSynchronously
        this.IsLoading <- false

所以我在我的视图中的 OnAppearing() 方法中执行了 SetData() 函数,我的 FacebookProfile 和 PostsDb 数据很好地绑定到我的 ListView 并且它显示正确。 问题是当它通过 SetData() 时,我的 ActivityIndi​​cator 从未出现过。 但是,如果我删除 this.IsLoading <- false 行,它会正确显示(并且不会明显消失) 在我的调试控制台中,我没有绑定错误,即使在调试模式下,我也看到我的 IsLoading 属性 已更改。

我只想说,我知道以这种方式使用 F# 并不正确,而且会产生难看的 F# 代码,但这只是使用 F# 的测试 class。

我怀疑你的问题是这 4 行都是同步执行的,因此即使你 this.IsLoading <- true 一开始是正确的, UI 也永远不会收到该消息,因为你的执行是基本上锁定了 4 行:

this.IsLoading <- true
this.FacebookProfile <- GetProfileData() |> Async.RunSynchronously
this.PostsDb <- GetPostData() |> Async.RunSynchronously
this.IsLoading <- false

您需要通过首先创建一个异步工作流找到一种异步 运行 它们的方法:

async {
    this.IsLoading <- true
    let! profileData = GetProfileData()
    let! postData = GetPostData()
    this.FacebookProfile <- profileData
    this.PostsDb <- postData
    this.IsLoading <- false
}

然后决定您将如何处理该工作流,如果调用 GetData() 的代码可以处理任务,您可以将其通过管道传输到 startAsTask:

member this.SetDataAsync() =
    async {
        // copy code from above
    }
    |> Async.startAsTask