[C#] HTTP로 JSON을 받아와서 ListView에 표시하는 샘플

스크린샷 2014-05-19 오후 8.15.01

이 회사 오기 전에 며칠 공부했었던 것 같은데, 당연히 다 까먹었고, 오늘의 목표는 이거다.

 

스크린샷 2014-05-19 오후 8.17.46

새 프로젝트를 만든다. Visual C#과 WPF를 선택한다.

 

 

 

레이아웃 그리기

스크린샷 2014-05-19 오후 8.25.26

<Window x:Class="ListViewSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="773">
    <Grid>
        <Button Content="Clear" HorizontalAlignment="Right" Margin="0,10,10,0" VerticalAlignment="Top" Width="75" Click="Clear_Button_Click"/>
        <Button Content="Refresh" HorizontalAlignment="Right" Margin="0,10,90,0" VerticalAlignment="Top" Width="75" Click="Refresh_Button_Click"/>
        <ListView x:Name="IssueListView" Margin="10,42,10,10">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Subject" Width="580" DisplayMemberBinding="{Binding Subject}"/>
                    <GridViewColumn Header="Author" Width="100" DisplayMemberBinding="{Binding Author}"/>
                    <GridViewColumn Header="Done %" Width="50" DisplayMemberBinding="{Binding Done}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

 

DisplayMemberBinding=”{Binding Subject}” 이 부분이 데이터가 연결되는 부분이다. 설정하는 화면이 따로 있을 것 같은 느낌이지만, 오늘은 맨땅에 헤딩이라 패스한다.

 

 

 

HTTP GET으로 JSON 호출하기

먼저 JSON 라이브러리를 받아와야 한다. 이게 제일 유명한 것 같다. http://james.newtonking.com/json

 

받은 파일을 압축해제하면 Bin – Netxx – Newtonsoft.Json.dll 이 나온다.

 

프로젝트에 dll 을 추가한다.

스크린샷 2014-05-19 오후 8.37.04 스크린샷 2014-05-19 오후 8.37.41

 

 

using Newtonsoft.Json.Linq;
using System.Net;
using System.IO;

.
.
.

private string Request_Json()
{
    string result = null;
    string url = "http://www.redmine.org/issues.json";
    Console.WriteLine("url : " + url);

    try
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        Stream stream = response.GetResponseStream();
        StreamReader reader = new StreamReader(stream);
        result = reader.ReadToEnd();
        stream.Close();
        response.Close();
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }

    return result;
}

Refresh 버튼을 누르면 http로 json 을 가져온다.

 

 

Issue 클래스 만들기

스크린샷 2014-05-19 오후 8.44.27 스크린샷 2014-05-19 오후 8.44.49

Issue.cs 클래스를 추가한다.

 

namespace ListViewSample
{
    class Issue
    {
        public string Subject { get; set; }
        public string Done { get; set; }
        public string Author { get; set; }
    }
}

 

 

JSON Parse

받아 온 json 문자열을 파싱하고, ItemsResources 에다 넣어주면 된다.

 

http://www.redmine.org/issues.json

스크린샷 2014-05-19 오후 8.49.53

요렇게 생겼다.

 

private void ParseJson(String json)
{
    List<Issue> issues = new List<Issue>();

    JObject obj = JObject.Parse(json);
    JArray array = JArray.Parse(obj["issues"].ToString());
    foreach (JObject itemObj in array)
    {
        Issue issue = new Issue();
        issue.Subject = itemObj["subject"].ToString();
        issue.Done = itemObj["done_ratio"].ToString();
        issue.Author = itemObj["author"]["name"].ToString();
        issues.Add(issue);
    }

    IssueListView.ItemsSource = issues;
}

 

 

Button Click 연결하기

이제 남은 건 버튼을 클릭했을 때 함수만 호출시켜주면 된다.

private void Refresh_Button_Click(object sender, RoutedEventArgs e)
{
    string json = this.Request_Json();
    this.ParseJson(json);
}

private void Clear_Button_Click(object sender, RoutedEventArgs e)
{
    IssueListView.ItemsSource = null;
}

 

 

전체 소스

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Newtonsoft.Json.Linq;
using System.Net;
using System.IO;

namespace ListViewSample
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Refresh_Button_Click(object sender, RoutedEventArgs e)
        {
            string json = this.Request_Json();
            this.ParseJson(json);
        }

        private string Request_Json()
        {
            string result = null;
            string url = "http://www.redmine.org/issues.json";
            Console.WriteLine("url : " + url);

            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream stream = response.GetResponseStream();
                StreamReader reader = new StreamReader(stream);
                result = reader.ReadToEnd();
                stream.Close();
                response.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            return result;
        }

        private void ParseJson(String json)
        {
            List<Issue> issues = new List<Issue>();

            JObject obj = JObject.Parse(json);
            JArray array = JArray.Parse(obj["issues"].ToString());
            foreach (JObject itemObj in array)
            {
                Issue issue = new Issue();
                issue.Subject = itemObj["subject"].ToString();
                issue.Done = itemObj["done_ratio"].ToString();
                issue.Author = itemObj["author"]["name"].ToString();
                issues.Add(issue);
            }

            IssueListView.ItemsSource = issues;
        }

        private void Clear_Button_Click(object sender, RoutedEventArgs e)
        {
            IssueListView.ItemsSource = null;
        }
    }
}

 

 

Async

아니 요새 누가 이런 네트웍 작업에 async를 안쓰겠냐 ㅋㅋ

private async void Refresh_Button_Click(object sender, RoutedEventArgs e)
{
    string json = await RequestJson();
    this.ParseJson(json);
}

async void 로 바꾼다.

 

private async Task<string> RequestJson()
{
    string url = "http://www.redmine.org/issues.json";
    HttpClient client = new HttpClient();
    Task<string> getStringTask = client.GetStringAsync(url);
    string result = await getStringTask;
    return result;
}

http://stackoverflow.com/questions/202481/how-to-use-httpwebrequest-net-asynchronously 여기를 참고해서 HttpWebRequest로 해봤는데, ItemsSource에 적용할 때 System.InvalidOperationException 가 나더라. 아마 request가 작업 중에 리스트뷰를 건들이면 안되는 것 같다.

 

 

using System.Net.Http;

이게 필요한데, 안되면  저 위에 Newtonsoft.Json.dll 추가하는 식으로 하면 된다.

 

 

https://github.com/susemi99/ListView-Sample