Заполнение наблюдаемой коллекции в виде списка из асинхронного метода - PullRequest
0 голосов
/ 29 августа 2018

У меня есть список, и я заполняю список методом, использующим цикл for. просто число от 1 до 10. Затем я создал представление списка и заполнил его коллекцией Observable, преобразовав список, полученный из метода, в коллекцию Observable. Во время выполнения этой программы я могу видеть представление списка, заполненное числами. но когда я заполняю тот же список с помощью асинхронного метода, я не вижу, как список заполняется. Я использовал точки останова, чтобы проверить, работают ли методы или нет. Но методы все работают нормально. даже моя наблюдаемая коллекция заселяется. но я не могу видеть представление списка.

Вот моя программа:

<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;
        }
    }
}

Мой класс

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, и я также включил этот оператор XMLNS: данные = "с использованием: UWPListView.Models" а также с использованием UWPListView.Models;

Ответы [ 3 ]

0 голосов
/ 29 августа 2018

Используйте код, который я предоставил ниже для вашего класса, я упростил для вас вещи.

Вам не нужно делать 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;
    }
}
0 голосов
/ 29 августа 2018

Не использовать Task.GetAwaiter () :

Этот метод предназначен для использования компилятором, а не для использования в коде приложения.

Я бы изменил ваше приложение так, чтобы вы подождали, пока страница загрузится, и в этот момент загрузите вашу модель:

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 ( ссылка ).

0 голосов
/ 29 августа 2018

Я бы предложил создать обработчик событий при загрузке страницы

Что-то вроде:

<Page
...
Loaded="MainPage_OnLoaded">

Тогда в вашем коде есть:

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

Вы также можете оставить конструктор, чтобы просто инициализировать элементы.

...