![](/img/trans.png)
[英]Group ListView by a component on a JSON in Xamarin.Forms
[英]Xamarin.Forms JSON object into Listview
我正在尝试解析此JSON对象,并将其绑定到Xamarin.Forms中的ListView。
由于我是Xamarin Forms的新手,我对如何处理它一无所知。
有没有更简单的方法可以做到这一点?
我返回的JSON对象
[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret"
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette"
}
]
这是我的代码来处理REST json响应
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
}
};
}
您的异步通话不正确。 如果必须在构造函数中执行此操作(这不是最佳选择),则需要使用ContinueWith来使用Task.Result。 同样,由于Result是一个阻塞调用,因此您要在构造列表视图之前分配项目源,并且会得到null引用异常。
尝试这个:
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);
}
});
}
}
一个更好的选择(但也不完美)是覆盖出现的方法,并且标记为异步。 这样,您可以在异步REST调用方法上使用await。 请注意,除非添加其他代码,否则每次视图出现时都会调用此方法。
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");
}
}
看起来您没有在等待sv.GetUsersAsync,而且我不确定Result是否将包含所有数据,而无需等待操作完成。
尽管可以将任何集合和任何对象用作列表视图的数据源,但最好使用ObservableCollection并让您的User类实现INotifyPropertyChanged(请看一下Fody.PropertyChanged nuget包)。
您可以与我们分享xaml吗?
编辑1
您定义两次ItemTemplate。
listView.ItemTemplate = new DataTemplate(typeof(TextCell)); //first definition
listView.ItemTemplate.SetBinding(TextCell.TextProperty, "username");
listView.ItemTemplate = new DataTemplate(typeof(ItemCell)); //second definition, remove it
此外,最好将MVVM与Xamarin.Forms一起使用,并在视图模型而不是页面的构造函数中加载数据。 这是一篇关于mvvm和Xamarin.Forms中的数据加载的好文章。
编辑2
为什么以这种奇怪的方式使用async / await? 与其阅读Task.Result属性,不如使用异步/等待对。 例子
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.