繁体   English   中英

Xamarin.Forms JSON对象进入Listview

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM