【问题标题】:Populate a ListView from a Json file in C#从 C# 中的 Json 文件填充 ListView
【发布时间】:2017-05-18 03:07:33
【问题描述】:

我正在使用 Xamarin 和 C# 创建一些基本的 Android 应用程序。 我正在学习中。

我想要做的是用从 JSON 文件中提取的一些数据填充 ListView。 我做了两种方法,一种是调用服务器的异步任务,另一种是解析和提取数据(http://mysafeinfo.com/api/data?list=englishmonarchs&format=json)。

我现在的问题是我不知道如何为列表视图提供这些数据。

感谢您的宝贵时间。

namespace App4 
{
[Activity(Label = "App4", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    //Declare a Cancellation Token Source 
    CancellationTokenSource cts;

    Button startbutton;
    Button stopbutton;
    TextView textView0;
    ListView listView;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.Main);

        startbutton = FindViewById<Button>
            (Resource.Id.startbutton);
        stopbutton = FindViewById<Button>
            (Resource.Id.stopbutton);
        textView0 = FindViewById<TextView>
            (Resource.Id.textView0);
        listView = FindViewById<ListView>
            (Resource.Id.listView);


        //BASIC ASYNC START TASK
        // click the startbutton to start the process
        startbutton.Click += async (sender, e) =>
        {                
            // Instantiate the CancellationTokenSource
            cts = new CancellationTokenSource();

            try
            {
                // **** GET ****
               await Task.Run(() => LoadDataAsync(cts.Token));

            }
            catch (TaskCanceledException)
            {
                textView0.Text = " Download deleted ";
            }
            catch (Exception)
            {
                textView0.Text = "Generic Error";
            }

            // ***Set the CancellationTokenSource to null when the download is complete.
            cts = null;
        };

        //STOP BUTTON 
        stopbutton.Click += (sender, e) =>
        {
            if (cts != null)
            {
                cts.Cancel();
            }
        };
    }

    //THIS METHOD LOAD JSON DATA FROM AN URL AND RETURN A STRING

    public static async Task<string> LoadDataAsync(CancellationToken ct)
    {
        // Call the server and take the file
        var client = new HttpClient();
        client.MaxResponseContentBufferSize = 1024 * 1024; //read up to 1MB of data

        await Task.Delay(250);//Delay the task for deleting purpose

        var response = await client.GetAsync(new Uri("http://mysafeinfo.com/api/data?list=englishmonarchs&format=json"), ct);
        var result = await response.Content.ReadAsStringAsync();

        return result;

    }

    //THIS METHOD GET THE JSON DATA FROM THE STRING 

    private static void GetData(string result)
    {

        // Parse the Json file.
        JArray file = JArray.Parse(result);

        foreach (var item in file.Children<JObject>())
        {               
            string name = (string)item.SelectToken("nm");
            string city = (string)item.SelectToken("cty");
            string house = (string)item.SelectToken("hse");
            string years = (string)item.SelectToken("yrs");
        }
    }

}

}

【问题讨论】:

  • 您需要创建一个域对象,该对象具有每个数据元素(名称、城市等)的属性,然后在您的 GetData 方法中创建这些对象的列表。他们使用 ListAdapter 将该数据提供给您的 ListView

标签: c# json listview xamarin


【解决方案1】:

您需要一些东西,并建议您更改其他一些东西,以便更容易。

首先使用您将从 API 接收的数据创建一个实体/类。随心所欲地调用它,但对于这个例子,我将它命名为 EnglishMonarch

public class EnglishMonarch
{
    public string Name {get; set;}

    public string City {get; set;}

    public string House {get; set;}

    public string Years {get; set;}
}

如您所见,我为您将收到的每个字段添加了一个公共属性。

我建议您使用这个库Json.net,它可以让您只用几行代码将 json 数据解析到您的实体中。您可以直接从 XS 或 VS 安装 nuget 包。

您需要对我们刚刚创建的类进行一些更改。您将添加一些注释,以便 json.net 知道如何将每个 json 字段映射到您的类属性。

public class EnglishMonarch
{
    [JsonProperty("nm")]
    public string Name { get; set; }

    [JsonProperty("cty")]
    public string City { get; set; }

    [JsonProperty("hse")]
    public string House { get; set; }

    [JsonProperty("yrs")]
    public string Years { get; set; }
}

现在您可以像这样使用 json.net 获取响应并对其进行解析:

public List<EnglishMonarch> GetData (string jsonData)
{
    if (string.IsNullOrWhiteSpace (jsonData))
        return new List<EnglishMonarch> ();

    return JsonConvert.DeserializeObject<List<EnglishMonarch>> (jsonData);
}

注意:为什么要列出EnglishMonarch?因为您从 API 接收到的项目不止一项,这是您将用于填充 ListView 的列表。

现在让我们将这些数据放入您的 ListView。在 Android 中,您需要创建一个 Adapter,它告诉 ListView 如何以及显示什么数据。

您的适配器将如下所示:

public class EnglishMonarchAdapter : BaseAdapter<EnglishMonarch>
{
    public List<EnglishMonarch> Items { get; set;}

    private readonly Context context;

    public EnglishMonarchAdapter (Context context, List<EnglishMonarch> items)
    {
        this.context = context;

        Items = items ?? new List<EnglishMonarch> ();
    }

    public override EnglishMonarch this [int position]
    {
        get { return Items [position]; }
    }

    public override int Count
    {
        get { return Items.Count; }
    }

    public override long GetItemId (int position)
    {
        return position;
    }

    public override View GetView (int position, View convertView, ViewGroup parent)
    {
        var view = convertView ?? LayoutInflater.FromContext (context).Inflate (Resource.Layout.englishmonarch_item_layout, parent, false);

        var item = Items [position];

        var tvName = view.FindViewById<TextView> (Resource.Id.tvName);
        var tvHouse = view.FindViewById<TextView> (Resource.Id.tvHouse);
        var tvYear = view.FindViewById<TextView> (Resource.Id.tvYears);
        var tvCity = view.FindViewById<TextView> (Resource.Id.tvCity);

        tvName.Text = item.Name;
        tvHouse.Text = item.House;
        tvYear.Text = item.Years;
        tvCity.Text = item.City;

        return view;
    }
}

GetView 方法负责创建 ListView 项目视图(单元格)并将数据映射到视图中的字段。

要使此适配器工作,您需要创建一个布局 (XML),该布局将用作 ListView 的 ItemView/Cell。我创建的非常简单,我将其命名为 englishmonarch_item_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tvName"
        android:textSize="16sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/tvCity" 
        android:textSize="14sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/tvHouse" 
        android:textSize="11sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/tvYears" 
        android:textSize="11sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>  
</LinearLayout>

现在您只需在 startButton 点击事件中粘贴一些片段

    startbutton.Click += async (sender, e) =>
    {                
        // Instantiate the CancellationTokenSource
        cts = new CancellationTokenSource();

        try
        {
            // **** GET ****
           var jsonData = await LoadDataAsync(cts.Token);

           // ** Parse data into your entity ****
           var items = GetData(jsonData);

           // **** Create your adapter passing the data *****
           listview.Adapter = new EnglishMonarchAdapter(this, items);
        }
        catch (TaskCanceledException)
        {
            textView0.Text = " Download deleted ";
        }
        catch (Exception)
        {
            textView0.Text = "Generic Error";
        }

        // ***Set the CancellationTokenSource to null when the download is complete.
        cts = null;
    };

就是这样。应该可以!

注意:您可以跳过一些部分,例如使用 Json.net 并手动解析您的数据,只是提到它是为了让您知道还有其他选择。

【讨论】:

  • 这是一个完整而非凡的答案。非常感谢您的宝贵时间!
猜你喜欢
  • 2011-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
相关资源
最近更新 更多