이 회사 오기 전에 며칠 공부했었던 것 같은데, 당연히 다 까먹었고, 오늘의 목표는 이거다.
새 프로젝트를 만든다. Visual C#과 WPF를 선택한다.
레이아웃 그리기
<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 을 추가한다.
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 클래스 만들기
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
요렇게 생겼다.
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