在C#中使用Json文件填充ListView

时间:2017-05-18 03:07:34

标签: c# json listview xamarin

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

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

我现在的问题是我不知道如何用这些数据提供listview。

感谢您的时间。

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");
        }
    }

}

}

1 个答案:

答案 0 :(得分: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项目视图(Cell)并将数据映射到视图中的字段。

要使此适配器工作,您需要创建一个布局(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并手动解析数据,只是提到它,以便您知道其他选项。