OpenAPI Project / MahApp

오윤범·2023년 4월 28일
0

MiniProject

목록 보기
4/8

부산 연극 정보 앱

해당 프로젝트 깃허브 주소

https://github.com/OHYUNBEOM/WPF
https://github.com/OHYUNBEOM/WPF/tree/main/OpenAPIProject/wpf_OpenAPI

기술 스택

  • MahApps

  • OpenAPI

  • MySQL

1) 공공 데이터 포털 API 신청

https://www.data.go.kr/iim/api/selectAPIAcountView.do

부산 연극 정보 API

https://apis.data.go.kr/6260000/BusanCulturePlayService/getBusanCulturePlay?serviceKey=te5%2FahqxnGW00Gw1jJ92lJYLwkOvVrP9DZdSdffoIyZB8Jb%2BzHMrpMxU0VQOlxdvK%2BRzzcNsLTr%2BLaoLfFzUQg%3D%3D&pageNo=1&numOfRows=734&resultType=json

2) 누겟 패키지 설치

  • MahApps.Metro
  • MahApps.Metro.Icon
  • Newtonsoft.Json
  • MySql.Data

3) MySQL 테이블 생성

MySql 초기 상태

App.xaml

<Application x:Class="wpf_OpenAPI.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:wpf_OpenAPI"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <!-- Theme setting -->
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Crimson.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

MainWindow.xaml

<mah:MetroWindow x:Class="wpf_OpenAPI.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
        xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
        xmlns:local="clr-namespace:wpf_OpenAPI"
        mc:Ignorable="d"
        Title="부산 연극 정보" Height="600" Width="1600" FontFamily="NanumGothic">

    <mah:MetroWindow.IconTemplate>
        <DataTemplate>
            <iconPacks:PackIconPixelartIcons Kind="Movie" Foreground="White" Margin="5,7,0,0"/>
        </DataTemplate>
    </mah:MetroWindow.IconTemplate>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="80"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="25"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>

        <Grid Grid.Row="0" Grid.Column="0">
            <Label Content="Busan Play Information" FontSize="30" FontWeight="Bold" Margin="10" HorizontalAlignment="Center" FontStyle="Italic"/>
        </Grid>

        <StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
            <Button x:Name="BtnPlaySearch" Content="부산 연극 조회" Margin="5" Style="{StaticResource MahApps.Styles.Button.Dialogs.Accent}" Width="130" Click="BtnPlaySearch_Click"/>
            <Button x:Name="BtnPlayInsertDB" Content="저장" Margin="5" Style="{StaticResource MahApps.Styles.Button.Dialogs.Accent}" Width="80" Click="BtnPlayInsertDB_Click"/>
            <TextBox Width="230"  x:Name="TxtPlayName" FontSize="15" Margin="5,10,5,20"
                     mah:TextBoxHelper.Watermark="검색할 연극명 입력"
                     mah:TextBoxHelper.UseFloatingWatermark="True"
                     mah:TextBoxHelper.ClearTextButton="True"
                     InputMethod.PreferredImeState="On"
                     InputMethod.PreferredImeConversionMode="Native" KeyDown="TxtPlayName_KeyDown"/>
            <Button x:Name="BtnSearchPlay" Content="검색" Margin="5" Style="{StaticResource MahApps.Styles.Button.Dialogs.Accent}" Width="60" Click="BtnSearchPlay_Click"/>
        </StackPanel>

        <!--데이터 그리드-->
        <DataGrid Grid.Row="1" Grid.ColumnSpan="2" x:Name="GrdResult" Style="{StaticResource MahApps.Styles.DataGrid.Azure}" Margin="10,10,10,10"
              IsReadOnly="True" ItemsSource="{Binding}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Title}" Header="제목" FontWeight="Bold" Width="590"/>
                <DataGridTextColumn Binding="{Binding Place_nm}" Header="시설명" FontWeight="Bold" Width="370"/>
                <DataGridTextColumn Binding="{Binding Op_st_dt}" Header="공연시작일" FontWeight="Bold" Width="160"/>
                <DataGridTextColumn Binding="{Binding Op_ed_dt}" Header="공연종료일" FontWeight="Bold" Width="160"/>
                <DataGridTextColumn Binding="{Binding Pay_at}" Header="유무료 구분" FontWeight="Bold" Width="80"/>
                <DataGridTextColumn Binding="{Binding Op_at}" Header="오픈런" FontWeight="Bold" Width="60"/>
                <DataGridTextColumn Binding="{Binding Res_no}" Header="공연번호" FontWeight="Bold" Width="100"/>
            </DataGrid.Columns>

        </DataGrid>

        <!--상태 바-->
        <StatusBar Grid.Row="2" Grid.ColumnSpan="2" Grid.RowSpan="2" Margin="0,0,0,0">
            <StatusBarItem Content="부산 연극 정보 조회 앱 "/>
            <Separator Style="{StaticResource MahApps.Styles.Separator.StatusBar}"/>
            <StatusBarItem x:Name="StsResult"/>
        </StatusBar>

    </Grid>
</mah:MetroWindow>

Mainwindow.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
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 MahApps.Metro.Controls;
using MySql.Data.MySqlClient;
using Newtonsoft.Json.Linq;
using wpf_OpenAPI.Logics;
using wpf_OpenAPI.Models;
using wpf_OpenAPI.Logics;
using wpf_OpenAPI.Models;
using System.Diagnostics;
using System.Data;

namespace wpf_OpenAPI
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        // 부산 연극 정보 API 조회
        private async void BtnPlaySearch_Click(object sender, RoutedEventArgs e)
        {
            string key = "te5%2FahqxnGW00Gw1jJ92lJYLwkOvVrP9DZdSdffoIyZB8Jb%2BzHMrpMxU0VQOlxdvK%2BRzzcNsLTr%2BLaoLfFzUQg%3D%3D";
            string openApiUri = $"https://apis.data.go.kr/6260000/BusanCulturePlayService/getBusanCulturePlay?serviceKey={key}&numOfRows=734&resultType=json";
            string result = string.Empty;
            //WebRequest,WebResponse
            WebRequest req = null;
            WebResponse res = null;
            StreamReader reader = null;
            try
            {
                req = WebRequest.Create(openApiUri);
                res = await req.GetResponseAsync();
                reader = new StreamReader(res.GetResponseStream());
                result = reader.ReadToEnd();
            }
            catch (Exception ex)
            {
                await Commons.ShowMessageAsync("오류", $"OpenAPI 조회오류 {ex.Message}");
            }

            var jsonResult = JObject.Parse(result);
            var status = Convert.ToInt32(jsonResult["code"]);

            try
            {
                if(status==00)
                {
                    var data = jsonResult["getBusanCulturePlay"]["item"];
                    var json_array = data as JArray;

                    var playinfors = new List<PlayInfor>();
                    foreach (var infor in json_array)
                    {
                        playinfors.Add(new PlayInfor
                        {
                            Id=0,
                            Res_no = Convert.ToInt32(infor["res_no"]),
                            Title = Convert.ToString(infor["title"]),
                            Op_st_dt = Convert.ToDateTime(infor["op_st_dt"]),
                            Op_ed_dt = Convert.ToDateTime(infor["op_ed_dt"]),
                            Op_at = Convert.ToString(infor["op_at"]),
                            Place_nm = Convert.ToString(infor["place_nm"]),
                            Pay_at = Convert.ToString(infor["pay_at"])
                        });
                    }
                    this.DataContext= playinfors;
                    StsResult.Content = $"부산 연극 정보 {playinfors.Count}건 조회 완료";
                }
            }
            catch (Exception ex)
            {
                await Commons.ShowMessageAsync("오류", $"JSON 처리오류 {ex.Message}");
            }

        }
        //조회된 연극정보 DB(MySQL)에 저장
        private async void BtnPlayInsertDB_Click(object sender, RoutedEventArgs e)
        {
            if (GrdResult.Items.Count == 0)
            {
                await (Commons.ShowMessageAsync("오류", "연극 정보 조회 이후 저장하세요!"));
                return;
            }
            //DB에 저장
            try
            {
                using (MySqlConnection conn = new MySqlConnection(Commons.myConnString))
                {
                    if (conn.State == System.Data.ConnectionState.Closed) conn.Open();
                    var query = @"INSERT INTO playinfor
                                (
                                Res_no,
                                Title,
                                Op_st_dt,
                                Op_ed_dt,
                                Op_at,
                                Place_nm,
                                Pay_at)
                                VALUES
                                (
                                @Res_no,
                                @Title,
                                @Op_st_dt,
                                @Op_ed_dt,
                                @Op_at,
                                @Place_nm,
                                @Pay_at)";
                    var insRes = 0;
                    foreach(var temp in GrdResult.Items)
                    {
                        if(temp is PlayInfor)
                        {
                            var item = temp as PlayInfor;
                            MySqlCommand cmd = new MySqlCommand(query, conn);

                            cmd.Parameters.AddWithValue("@Res_no", item.Res_no);
                            cmd.Parameters.AddWithValue("@Title", item.Title);
                            cmd.Parameters.AddWithValue("@Op_st_dt", item.Op_st_dt);
                            cmd.Parameters.AddWithValue("@Op_ed_dt", item.Op_ed_dt);
                            cmd.Parameters.AddWithValue("@Op_at", item.Op_at);
                            cmd.Parameters.AddWithValue("@Place_nm", item.Place_nm);
                            cmd.Parameters.AddWithValue("@Pay_at", item.Pay_at);

                            insRes += cmd.ExecuteNonQuery();
                        }
                    }
                    await Commons.ShowMessageAsync("저장", "DB 저장 성공!");
                    StsResult.Content = $"DB 저장 {insRes}건 성공!";
                }
            }
            catch (Exception ex)
            {
                await Commons.ShowMessageAsync("오류", $"DB저장 오류! {ex.Message}");
            }
        }

        private void TxtPlayName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                BtnSearchPlay_Click(sender, e);
            }
        }

        private async void BtnSearchPlay_Click(object sender, RoutedEventArgs e)
        {
            if(string.IsNullOrEmpty(TxtPlayName.Text))
            {
                await Commons.ShowMessageAsync("검색", "검색할 연극명 입력하세요.");
                return;
            }
            this.DataContext = null;
            var Search_playinfors = new List<PlayInfor>();
            //입력한 글자가 연극명에 포함된 연극 DB에서 찾아서 출력
            try
            {
                using (MySqlConnection conn = new MySqlConnection(Commons.myConnString))
                {
                    if (conn.State == ConnectionState.Closed) conn.Open();
                    var query = $@"SELECT Id,
	                               Res_no,
	                               Title,
	                               Op_st_dt,
	                               Op_ed_dt,
	                               Op_at,
	                               Place_nm,
	                               Pay_at
                                   FROM playinfor
                               WHERE Title LIKE '%{TxtPlayName.Text}%'";
                    var cmd = new MySqlCommand(query, conn);
                    var adapter = new MySqlDataAdapter(cmd);
                    var dSet = new DataSet();
                    adapter.Fill(dSet, "PlayInfor");
                    foreach(DataRow dr in dSet.Tables["PlayInfor"].Rows)
                    {
                        Search_playinfors.Add(new PlayInfor
                        {
                            Id = Convert.ToInt32(dr["Id"]),
                            Res_no = Convert.ToInt32(dr["res_no"]),
                            Title = Convert.ToString(dr["title"]),
                            Op_st_dt = Convert.ToDateTime(dr["op_st_dt"]),
                            Op_ed_dt = Convert.ToDateTime(dr["op_ed_dt"]),
                            Op_at = Convert.ToString(dr["op_at"]),
                            Place_nm = Convert.ToString(dr["place_nm"]),
                            Pay_at = Convert.ToString(dr["pay_at"])
                        });
                    }
                    this.DataContext = Search_playinfors;
                    StsResult.Content = $"{TxtPlayName.Text} 가 포함된 연극명 {Search_playinfors.Count}건 조회 완료!";
                }
            }
            catch (Exception ex)
            {
                await Commons.ShowMessageAsync("오류", $"오류 발생 : {ex.Message}");
            }
        }
    }
}

Logics/Commons.cs

using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace wpf_OpenAPI.Logics
{
    public class Commons
    {
        //MySQL용
        public static readonly string myConnString = "Server=localhost;" +
                                                     "Port=3306;" +
                                                     "Database=miniproject;" +
                                                     "Uid=root;" +
                                                     "Pwd=12345;";
        // 비동기 메시지 창
        public static async Task<MessageDialogResult> ShowMessageAsync(string title, string message,
            MessageDialogStyle style = MessageDialogStyle.Affirmative)
        {
            return await ((MetroWindow)Application.Current.MainWindow).ShowMessageAsync(title, message, style, null);
        }
    }
}

Models/PlayInfor.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace wpf_OpenAPI.Models
{
    public class PlayInfor
    {
        public int Id { get; set; }
        public int Res_no { get; set; }
        public string Title { get; set; }
        public DateTime Op_st_dt { get; set; }
        public DateTime Op_ed_dt { get; set; }
        public string Op_at { get; set; }
        public string Place_nm { get; set; }
        public string Pay_at { get; set; }
    }
}

실행화면

1) Main 화면

2) 부산 연극 조회 버튼 Click


총 734건의 연극 정보를 뿌려줌

3) 저장 버튼 --> DB에 연극 정보 저장

4) 연극명 입력 후 검색 버튼


DB에 저장된 TextBox의 글자가 포함된 연극 정보 추출

0개의 댓글