I'm trying parse this JSON object and bind it to my ListView in Xamarin.Forms.
I'm just totally lost on how to handle it as i'm completely new to Xamarin Forms.
Is there a easier way to do this?
My returned JSON Object
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret"
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette"
}
]
Here is the my Code to handle the REST json response
public class RestClient
{
public RestClient ()
{
}
public async Task<User[]> GetUsersAsync () {
var client = new System.Net.Http.HttpClient ();
client.BaseAddress = new Uri("http://jsonplaceholder.typicode.com");
var response = client.GetAsync("users");
var usersJson = response.Result.Content.ReadAsStringAsync().Result;
var rootobject = JsonConvert.DeserializeObject<Rootobject>(usersJson);
return rootobject.Users;
}
}
Users.cs
public class Rootobject
{
public User[] Users { get; set; }
}
public class User
{
public string id { get; set; }
public string username { get; set; }
}
ListView Form Code
var sv = new RestClient ();
var es = sv.GetUsersAsync();
Xamarin.Forms.Device.BeginInvokeOnMainThread (() => {
Debug.WriteLine("Found " + es.Result.Length + " users");
listView.ItemsSource = es.Result;
});
XAML
public ListViewPage ()
{
Title = "Users";
var sv = new RestClient ();
var es = sv.GetUsersAsync();
Xamarin.Forms.Device.BeginInvokeOnMainThread (() => {
Debug.WriteLine("Found " + es.Result.Length + " users");
listView.ItemsSource = es.Result;
});
listView = new ListView ();
listView.ItemTemplate = new DataTemplate(typeof(TextCell));
listView.ItemTemplate.SetBinding(TextCell.TextProperty, "username");
listView.ItemTemplate = new DataTemplate(typeof(ItemCell));
Content = new StackLayout {
Children = {
listView
}
};
}
Your async call is not correct. If you have to do it in the constructor (which isn't the best place to do this) you would want to use ContinueWith as using Task.Result should not be used. Also because the Result is a blocking call you are assigning the item source before the list view is constructed and you are getting a null reference exception.
Try this:
public class ListViewPage : ContentPage
{
private readonly ListView listView;
public ListViewPage()
{
Title = "Users";
this.listView = new ListView {ItemTemplate = new DataTemplate(typeof (TextCell))};
this.listView.ItemTemplate.SetBinding(TextCell.TextProperty, "username");
Content = new StackLayout
{
Children = { this.listView }
};
var sv = new RestClient();
var es = sv.GetUsersAsync().ContinueWith(t =>
{
if (t.Status == TaskStatus.RanToCompletion)
{
Debug.WriteLine("Found {0} users.", t.Result.Length);
Device.BeginInvokeOnMainThread(() => this.listView.ItemsSource = t.Result);
}
});
}
}
A slightly better option (but not perfect either) would be to override the appearing method and mark is async. This way you can use await on the async REST call method. Note that this would get called every time the view appears unless additional code is added.
protected override async void OnAppearing()
{
base.OnAppearing();
try
{
var sv = new RestClient();
// activate/show spinner here
this.listView.ItemsSource = await sv.GetUsersAsync();
// inactivate/hide spinner here
}
catch (Exception exception)
{
this.DisplayAlert("Error", exception.Message, "OK");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With