View在异步操作后不显示ViewModel属性更改

时间:2017-09-04 02:04:37

标签: c# asynchronous xamarin mvvmcross

我的ViewModel有一个30秒的数据刷新服务委托方法:

public Task OnDataRefreshed(List<MyType> data)
{
    this.Data = data;
    LongRunningGetDetailsAsync();
    return Task.FromResult(0);
} 

公共属性Data在视图中正确显示和刷新。

此处的目的不是等待异步任务(即发即弃)LongRunningGetDetailsAsync(),因为如果执行同步,它将在显示Data之前引入显着延迟。我想尽快显示Data,然后让异步任务按照自己的节奏获取详细信息,然后让视图绑定赶上。

private async Task LongRunningGetDetailsAsync()
{
    foreach (MyType dataitem in this.Data)
    {
        dataitem.Details = await _apiEndpointService.GetDetails(dataitem.Id);
    }
}

LongRunningGetDetailsAsync()是绑定未触发的位置。我在LongRunningGetDetailsAsync结束时设置了一个断点,观察Data.Details - Data.Details在那里,但它永远不会显示在视图中。

提前感谢您的时间!

修改 改为

public async Task OnDataRefreshed(ObservableCollection<MyType> data)
{
    this.Data = data;
    await LongRunningGetDetailsAsync();
} 
  • 仍有同样的问题。 Data绑定Mvx.MvxListView。如果列表很长并且项目恰好在视图之外,则一旦滚动到,它将显示更新的模型OK。

“数据”:

    public class MyType
    {
        public string MyProperty { get; set; }
        public string Details { get; set; }
    }

    private ObservableCollection<MyType> _data;
    public ObservableCollection<MyType> Data
    {
        get { return _data; }
        set
        {
            if (SetProperty(ref _data, value))
            {
                RaisePropertyChanged(() => Data);
            }
        }
    }

查看绑定:

        <Mvx.MvxListView
        local:MvxBind="ItemsSource Data"
        local:MvxItemTemplate="@layout/listitem" 
        ... />

listitem:

       <TextView local:MvxBind="Text MyProperty" ...
       <TextView local:MvxBind="Text Details" ...

2 个答案:

答案 0 :(得分:1)

首先,在您调用函数时使用await关键字并将您的函数标记为async

public async Task OnDataRefreshed(List<MyType> data)
{
    this.Data = data;
    await LongRunningGetDetailsAsync();
}

据我了解,您希望在获得每个项目后立即在UI中显示项目。如果您的绑定是正确的,上述更改应该满足您的需要。您应该使用ObservableCollection<>而不是List<>作为Data属性。

答案 1 :(得分:0)

由于您要更改Details属性,因此您需要让视图知道它已更改。您需要使用与Data属性相同的逻辑:

private string _details;
public string Details
{
    get { return _details; }
    set
    {
        if (SetProperty(ref _details, value))
        {
            RaisePropertyChanged(() => Details);
        }
    }
}

作为旁注,请尽量避免列表的设置者。在将来,您可能有其他逻辑连接到您的列表,当被覆盖时,只会使事情变得复杂。相反,由于它是ObservableCollection<T>公开的,因此您可以在getter的值上调用Clear然后Add