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

时间:2020-07-03 12:17:19

标签: f# c#-to-f#

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

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

<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#课:

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

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

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

1 个答案:

答案 0 :(得分:0)

我怀疑您的问题是这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