从异步方法将 Observable 集合填充到列表视图中

Populating Observable collection into List view from Async method

我有一个列表,我使用 for 循环的方法填充该列表。只是一个从 1 到 10 的数字。然后我创建了一个列表视图,并通过将从方法获得的列表转换为可观察集合来用可观察集合填充它。在执行这个程序时,我可以看到用数字填充的列表视图。 但是当我用异步方法填充同一个列表时,我看不到列表视图被填充。我使用断点来检查这些方法是否有效。但是这些方法都很好用。甚至我的可观察集合也会被填充。但是我看不到列表视图。

这是我的程序:

<Page
    x:Class="UWPListView.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWPListView"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility  /2006"
    xmlns:data="using:UWPListView.Models"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel>
            <ProgressRing IsActive="True" Width="50" Height="50"
                          Foreground="Red" Name="MyProgress"/>
            <TextBlock Text="ListItems" FontSize="30"/>
        </StackPanel>

        <ListView Grid.Row="1" ItemsSource="{x:Bind ListItems}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="data:ListItem">
                <TextBlock Text="{x:Bind Number}" VerticalAlignment="Center"Margin="10,0,0,0" Foreground="Red"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid> 
</Page>

Mainpage.xaml.cs

namespace UWPListView
{
    public sealed partial class MainPage : Page
    {
        private ObservableCollection<ListItem> ListItems;

        public MainPage()
        {
            this.InitializeComponent();
            ThisMethod().GetAwaiter();
        }

        private async Task ThisMethod()
        {
            MyProgress.Visibility = Visibility.Visible;
            ObservableCollection<ListItem> items = new ObservableCollection<ListItem>(await ListManager.GetItemsAsync());
            ListItems = items;
            MyProgress.Visibility = Visibility.Collapsed;
        }
    }
}

我的class

namespace UWPListView.Models
{
    public class ListItem
    {
        public float Number { get; set; }
    }

    public class ListManager
    {
        public async static Task<List<ListItem>> GetItemsAsync()
        {
            var listItems = new List<ListItem>();
            Rootobject temperatures = await getTemperatureAsync();

            for (int i = 0; i < 3; i++)
            {
                listItems.Add(new ListItem() { Number = temperatures.hourly.data[i].temperature });
            }
            return listItems;
        }

        private async static Task<Rootobject> getTemperatureAsync()
        {
            HttpClient client = new HttpClient();
            var jsonData = await client.GetStringAsync("https://api.darksky.net/forecast/apikey/13.08,80.27?units=si");
            var parsedData = JsonConvert.DeserializeObject<Rootobject>(jsonData);
            return parsedData;
        }
    }

我在 Models 文件夹下创建了这个 class 并且我还包含了这个语句 xmlns:数据="using:UWPListView.Models"使用 UWPListView.Models;

我建议在加载页面时创建一个事件处理程序

类似于:

<Page
...
Loaded="MainPage_OnLoaded">

然后在你的代码隐藏中你可以有:

private async void MainPage_OnLoaded(object sender, RoutedEventArgs e)
{
    await ThisMethod();
}

您可能还想保留构造函数来仅初始化成员。

使用我在下面为您提供的代码 class,我已经为您简化了一些事情。

您不需要在构造函数中执行 GetAwaiter() 这会使事情复杂化。

您还需要在构造函数中初始化 observableCollection

public sealed partial class MainPage : Page
{
    private ObservableCollection<ListItem> ListItems;

    public MainPage()
    {
        this.InitializeComponent();
        this.Loaded += MainPageLoaded; //if you dont want to use loaded method u can use OnnavigatedTo() override as well.
        ObservableCollection<ListItem> ListItems = new ObservableCollection<ListItem>();
    }

    private async void MainPageLoaded(object sender, RoutedEventArgs e)
    {
        await ThisMethod();
    }

    private async Task ThisMethod()
    {
        MyProgress.Visibility = Visibility.Visible;
        var items = await ListManager.GetItemsAsync();
        foreach(var item in items)
        {
            ListItems.Add(item);
        }
        MyProgress.Visibility = Visibility.Collapsed;
    }
}

不要使用 Task.GetAwaiter():

This method is intended for compiler use rather than for use in application code.

我会修改您的应用程序,以便您等到页面加载完毕,然后加载您的模型:

namespace UWPListView
{
    public sealed partial class MainPage : Page
    {
        public ObservableCollection<ListItem> Model; // change your XAML to bind to Model instead of ListItems

        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += new RoutedEventHandler(OnLoaded);
        }

        private async void OnLoaded(object sender, RoutedEventArgs e)
        {
            MyProgress.Visibility = Visibility.Visible;
            this.Model = await ListManager.GetItemsAsync();
            MyProgress.Visibility = Visibility.Collapsed;
        } 
    }
}

请注意,事件处理程序是唯一应该使用 async void 而不是 async Task 的地方之一 (reference)。