Reputation: 3
I am having a list and i populate the list with a method using for loop. just a number from 1 - 10. Then i created a list view and populate it with Observable collection by converting the list i get from method into observable collection. While executing this program i can able to see the list view populated with numbers. but when i populate the same list with async method i can't see the list view get populate. I used the breakpoints to check whether the methods are working or not. But the methods are all working fine. even my observable collection get populated. but i can't able see the list view.
Here's my program:
<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;
}
}
}
My 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;
}
}
I have created this class under the Models folder and i also included this statements xmlns:data="using:UWPListView.Models" and using UWPListView.Models;
Upvotes: 0
Views: 2337
Reputation: 4455
Use the code I provided below for your class, I have simplified things for you.
You don't need to do GetAwaiter()
in the constructor that can complicate stuff.
Also you need to initialize the observableCollection within the constructor.
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;
}
}
Upvotes: 0
Reputation: 1924
Don't use Task.GetAwaiter():
This method is intended for compiler use rather than for use in application code.
I would modify your app so that you wait until the page is loaded, and at that point, load your model:
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;
}
}
}
Note that event handlers are one of the only places where async void
should be used instead of async Task
(reference).
Upvotes: 0
Reputation: 959
I'd suggest create an event handler when the Page is loaded
Something like:
<Page
...
Loaded="MainPage_OnLoaded">
Then on your code-behind you can have:
private async void MainPage_OnLoaded(object sender, RoutedEventArgs e)
{
await ThisMethod();
}
You may also want to leave the constructor for just initializing the members.
Upvotes: 1