Reputation: 794
I'm trying to add some sample data to an observable collection by declaring a new instance of the Posts class within a private async void and populating the collection. When the app loads, it doesn't show the content. Code compiles with no errors/warnings.
If I was to add the sample data within the Posts() method it's then displayed as expected.
How can I populate my observable collection from within my private async void and have the content displayed when the app is launched?
XAML:
<ListView ItemsSource="{StaticResource Posts}"
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}/>
<TextBlock Text="{Binding Author}/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C#
public class Data2 {
public string Title { get; set; }
public string Author { get; set; }
public Data2(string title, string author) {
this.Title = title;
this.Author = author;
}
}
public class Posts : ObservableCollection<Data2> {
public Posts() {
}
}
public sealed partial class MainPage : Page {
public MainPage() {
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
GetPosts();
}
protected override void OnNavigatedTo(NavigationEventArgs e) {
}
private async void GetPosts() {
try {
var client = new HttpClient();
var response = await client.GetAsync(new Uri("http://mywebsite.com/posts.json"));
var result = await response.Content.ReadAsStringAsync();
var json = ParseData(result);
Posts posts = new Posts();
posts.Add(new Data2("Sample Title 1", "Sample Author 1"));
posts.Add(new Data2("Sample Title 2", "Sample Author 2"));
}
catch(HttpRequestException hre) {
System.Diagnostics.Debug.WriteLine(hre);
}
catch(Exception ex) {
System.Diagnostics.Debug.WriteLine(ex);
}
}
private static RootObject ParseData(string json) {
return JsonConvert.DeserializeObject<RootObject>(json);
}
}
Upvotes: 0
Views: 94
Reputation: 1953
The line above:
<ListView ItemsSource="{StaticResource Posts}">
should work only if you have previously declared your Static Resouce, as fallows:
myWindow.Resources.Add("Posts", Posts);
It would be better to use dynamic, though.
You could set your Window data context to your Posts
class and do the async call to fill the data inside the Posts
constructor. Then use:
<ListView ItemsSource="{Binding Posts}">
You should see the data as soon as you get the response.
Upvotes: 0
Reputation: 102793
I suggest creating a view model for the "Posts" property:
public class PostsViewModel
{
public Posts PostData { get; private set; }
public PostsViewModel()
{
PostData = new Posts();
GetPosts();
}
private async void GetPosts()
{
// ...
}
}
Now set the page's DataContext to an instance of the view model:
public sealed partial class MainPage : Page {
private readonly PostsViewModel _viewmodel;
public MainPage() {
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
_viewmodel = new PostsViewModel();
}
}
And bind the ListView's ItemsSource to the property in the view model:
<ListView ItemsSource="{Binding Posts}"
(Of course, you could instead just put the collection in the page's code-behind and set DataContext=this
, but it is a good idea in general to separate the view-model logic.)
Upvotes: 2