23.04.25 Day61

오윤범·2023년 4월 25일
0

https://console.cloud.google.com/welcome?project=invertible-vent-315511
--> 구글 API 생성

  • MovieFinder2023 API 프로젝트 생성
  • 라이브러리 - YouTube Data API v3 - 사용
  • 사용자 인증 정보 만들기 - api 키 따로 작성 후 완료
  • OAuth 동의 화면 - 외부 - 만들기 - MovieFinder2023 / 내 이메일 주소 작성 / 개발자 연락처 정보에 내 이메일 주소 작성

MovieFinder

1) 참조 - Nuget 패키지 관리 - MahApps.Metro 설치
2) App.xaml의 Application.Resources 부분 수정
3) https://www.themoviedb.org/ API 발급

4) Youtube Api Key(구글에서 발급)
https://console.cloud.google.com/
AIzaSyCRs0FAqizh_j_LMqren845f3Bwrs4Nhk8

5) 참조 - 참조추가 - System.Web 추가
6) 참조 - 누겟 패키지 관리 - Newtonsoft.Json 설치

App.xaml

<Application x:Class="wpf11_MovieFinder.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:wpf11_MovieFinder"
             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.Emerald.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

MainWindow.xaml

<mah:MetroWindow x:Class="wpf11_MovieFinder.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:wpf11_MovieFinder"
        mc:Ignorable="d"
        Title="moviefinder 2023" Height="450" Width="800" MinHeight="385" MinWidth="645"
                 FontFamily="NanumGothic">
    <Grid Margin="10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="60"/>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="80"/>
        </Grid.RowDefinitions>
        <!--영화명 검색 부분-->
        <Grid Grid.Row="0" Grid.Column="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="3*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>

            <TextBox x:Name="TxtMovieName" Grid.Column="0" FontSize="14" Margin="5,10"
                     mah:TextBoxHelper.Watermark="검색할 영화명 입력"
                     mah:TextBoxHelper.UseFloatingWatermark="True"
                     mah:TextBoxHelper.ClearTextButton="True"
                     KeyDown="TxtMovieName_KeyDown"/>
            <Button x:Name="BtnSearchMovie" Grid.Column="1" FontSize="14" Margin="5,10"
                    Content="검색" Style="{StaticResource MahApps.Styles.Button.Square.Accent}" Click="BtnSearchMovie_Click">
                <Button.ContentTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <iconPacks:PackIconModern Kind="Magnify" Margin="5"/>
                            <TextBlock Text="{Binding}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </Button.ContentTemplate>
            </Button>
        </Grid>

        <!--데이터 그리드 영역-->
        <DataGrid x:Name="GrdResult" Grid.Row="1" Grid.Column="0" Margin="5"
                  IsReadOnly="True" Style="{StaticResource MahApps.Styles.DataGrid.Azure}"
                  ItemsSource="{Binding}"/>

        <!--포스터 영역-->
        <Grid Grid.Row="0" Grid.Column="1" Grid.RowSpan="2">
            <GroupBox Header="포스터" Margin="10"
                      mah:HeaderedControlHelper.HeaderFontSize="15"
 mah:HeaderedControlHelper.HeaderHorizontalContentAlignment="Center"
                      mah:HeaderedControlHelper.HeaderFontFamily="NanumGothic"
                      mah:HeaderedControlHelper.HeaderFontWeight="Bold">
                <Image x:Name="ImgPoster" Source="No_Picture.png" Margin="15,5"/>
            </GroupBox>
        </Grid>

        <!--버튼 영역-->
        <StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal">
            <Button x:Name="BtnAddFavorite" Content="즐겨찾기 추가" Margin="5,20" FontSize="12"
                    Style="{StaticResource MahApps.Styles.Button.Square.Accent}">
                <Button.ContentTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <iconPacks:PackIconModern Kind="ListAdd" Margin="5"/>
                            <TextBlock Text="{Binding}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </Button.ContentTemplate>
            </Button>
            <Button x:Name="BtnViewFavorite" Content="즐겨찾기 보기" Margin="5,20" FontSize="12"
                    Style="{StaticResource MahApps.Styles.Button.Square.Accent}">
                <Button.ContentTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <iconPacks:PackIconModern Kind="List" Margin="5"/>
                            <TextBlock Text="{Binding}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </Button.ContentTemplate>
            </Button>
            <Button x:Name="BtnDelFavorite" Content="즐겨찾기 삭제" Margin="5,20" FontSize="12"
                    Style="{StaticResource MahApps.Styles.Button}">
                <Button.ContentTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <iconPacks:PackIconModern Kind="ListDelete" Margin="5"/>
                            <TextBlock Text="{Binding}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </Button.ContentTemplate>
            </Button>
            <Button x:Name="BtnWatchTrailer" Content="예고편 보기" Margin="5,20" FontSize="12"
                    Style="{StaticResource MahApps.Styles.Button.Flat}">
                <Button.ContentTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <iconPacks:PackIconModern Kind="YoutubePlay" Margin="5"/>
                            <TextBlock Text="{Binding}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </Button.ContentTemplate>
            </Button>
            <Button x:Name="BtnNaverMovie" Content="네이버 영화" Foreground="#099A49" Margin="5,20" FontSize="12" Click="BtnNaverMovie_Click"
                    Style="{StaticResource MahApps.Styles.Button}">
                <Button.ContentTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image Source="naver.png" Width="20"/>
                            <TextBlock Text="{Binding}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </Button.ContentTemplate>
            </Button>
        </StackPanel>
    </Grid>
</mah:MetroWindow>

MainWindow.xaml.cs

using MahApps.Metro.Controls;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
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 wpf11_MovieFinder.Logics;
using wpf11_MovieFinder.Models;

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

        private  async void BtnNaverMovie_Click(object sender, RoutedEventArgs e)
        {
            await Commons.ShowMessageAsync("네이버 영화", "네이버 영화 사이트로 이동합니다!");
        }
        //네이버 API 사용 네이버 영화 검색 버튼
        private  async void BtnSearchMovie_Click(object sender, RoutedEventArgs e)
        {
            if(string.IsNullOrEmpty(TxtMovieName.Text))
            {
                await Commons.ShowMessageAsync("검색", "검색할 영화명을 입력하세요.");
                return;
            }
            if(TxtMovieName.Text.Length<=1)//두글자는 써줘라
            {
                await Commons.ShowMessageAsync("검색", "검색어를 2자이상 입력하세요.");
                return;
            }
            try
            {// 실제 검색 메서드
                SearchMovie(TxtMovieName.Text);
            }
            catch(Exception ex)
            {
                await Commons.ShowMessageAsync("오류", $"오류 발생 : {ex.Message}");
            }
        }
        //textBox에서 엔터 누를 시 검색
        private void TxtMovieName_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.Key==Key.Enter)
            {
                BtnSearchMovie_Click(sender, e);
            }
        }
        //실제 검색 메서드
        private  void SearchMovie(string movieName)
        {
            string tmdb_apiKey = "dd21bad55619f84e6e2823be028cbba2";
            string encoding_movieName = HttpUtility.UrlEncode(movieName, Encoding.UTF8);

            string openApiUri = $@"https://api.themoviedb.org/3/search/movie?api_key={tmdb_apiKey}&language=ko-KR&page=1&include_adult=false&query={encoding_movieName}";
            string result = string.Empty; //결과값

            //api 실행할 객체
            WebRequest req = null;
            WebResponse res = null;
            StreamReader reader = null;

            // TMDB API 요청
            try
            {
                req = WebRequest.Create(openApiUri);//URL을 넣어 객체 생성
                //Naver Api 헤더 설정
                res=req.GetResponse(); //요청한 결과를 응답에 할당
                reader = new StreamReader(res.GetResponseStream());
                result = reader.ReadToEnd();//json 결과 텍스트로 저장
                Debug.WriteLine(result);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                reader.Close();
                res.Close();
            }

            //result를 json으로 변경
            var jsonResult=JObject.Parse(result);
            var total = Convert.ToInt32(jsonResult["total_results"]);//전체 검색 결과 수
            var items = jsonResult["results"];
            //items를 데이터 그리드에 표시
            var json_array = items as JArray;
            var movieItems = new List<MovieItem>();//json에서 넘어온 배열을 담을 장소
            foreach(var val in json_array)
            {
                var MovieItem = new MovieItem()
                {
                    Id = Convert.ToInt32(val["id"]),
                    Title = Convert.ToString(val["title"]),
                    Original_Title = Convert.ToString(val["original_title"]),
                    Release_Date = Convert.ToString(val["release_date"]),
                    Vote_Average = Convert.ToDouble(val["vote_average"])
                };
                movieItems.Add(MovieItem);
            }
            this.DataContext=movieItems;
        }
    }
}

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 wpf11_MovieFinder.Logics
{
    internal class Commons
    {
        //매트로 다이얼로그창을 위한 정적 메서드
        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/Movieitem.cs

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

namespace wpf11_MovieFinder.Models
{
    public class MovieItem
    {
        public bool Adult { get; set; }
        public int Id { get; set; }
        public string Original_Language { get; set; }
        public string Original_Title { get; set;}
        public string Overview { get; set; }
        public double Popularity { get; set; }
        public string Poster_Path { get; set; }
        public string Release_Date { get; set; }
        public string Title { get; set; }
        public double Vote_Average { get; set; }
    }
}

0개의 댓글