23.04.26 Day62

dbsqja353·2023년 4월 26일
0

MovieFinder(MahApp,WPF)

  • 누겟 패키지 관리 - CefSharp.Wpf 설치 및 .xaml 수정
  • 누겟 패키지 관리 - Google.Apis.Youtube.v3 설치

1) 네이버 영화 버튼 삭제
2) 데이터 그리드 영역 Header 설정
3) TMDB API 이용 영화 클릭 시 포스터 출력
4) 예고편 보기
5) MSSql DB 생성 및 설계

  • 서버 탐색기 - 데이터 연결 - 연결 추가
  • 6) 프로젝트 구조 재 설계

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" Loaded="MetroWindow_Loaded">

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

    <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>
            <!--InputMethod...는 디폴트로 한글 입력 하기 위함-->
            <TextBox x:Name="TxtMovieName" Grid.Column="0" FontSize="14" Margin="5,10"
                     mah:TextBoxHelper.Watermark="검색할 영화명 입력"
                     mah:TextBoxHelper.UseFloatingWatermark="True"
                     mah:TextBoxHelper.ClearTextButton="True"
                     InputMethod.PreferredImeState="On"
                     InputMethod.PreferredImeConversionMode="Native"
                     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}" AutoGenerateColumns="False"
                  SelectedCellsChanged="GrdResult_SelectedCellsChanged">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Title}" Header="한글명" FontWeight="Bold"/>
                <DataGridTextColumn Binding="{Binding Original_Title}" Header="원제목"/>
                <DataGridTextColumn Binding="{Binding Release_Date}" Header="개봉일"/>
                <DataGridTextColumn Binding="{Binding Popularity,StringFormat={}{0:0.0}}" Header="인기도">
                    <DataGridTextColumn.ElementStyle>
                        <Style>
                            <Setter Property="TextBlock.TextAlignment" Value="Right"/>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding Vote_Average, StringFormat={}{0:0.0}}" Header="평점">
                    <DataGridTextColumn.ElementStyle>
                        <Style>
                            <Setter Property="TextBlock.TextAlignment" Value="Right"/>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>

        <!--포스터 영역-->
        <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}" Click="BtnAddFavorite_Click">
                <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}" Click="BtnWatchTrailer_Click">
                <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.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using wpf11_MovieFinder.Logics;
using wpf11_MovieFinder.Models;

namespace wpf11_MovieFinder
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        bool isFavorite = false; // false->openApi 검색해온 결과, true-> 즐겨찾기 보기 클릭
        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 async 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 = await req.GetResponseAsync(); //요청한 결과를 응답에 할당
                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()
                {
                    Adult = Convert.ToBoolean(val["adult"]),
                    Id = Convert.ToInt32(val["id"]),
                    Original_Language = Convert.ToString(val["original_language"]),
                    Original_Title = Convert.ToString(val["original_title"]),
                    Overview = Convert.ToString(val["overview"]),
                    Popularity = Convert.ToDouble(val["popularity"]),
                    Poster_Path = Convert.ToString(val["poster_path"]),
                    Release_Date = Convert.ToString(val["release_date"]),
                    Title = Convert.ToString(val["title"]),
                    Vote_Average = Convert.ToDouble(val["vote_average"])

                };
                movieItems.Add(MovieItem);
            }
            this.DataContext=movieItems;
        }

        private void MetroWindow_Loaded(object sender, RoutedEventArgs e)
        {
            TxtMovieName.Focus();
        }

        private void GrdResult_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
        {
            try
            {
                // 그리드에서 셀 선택 시 이벤트
                var movie = GrdResult.SelectedItem as MovieItem;
                //Debug.WriteLine(movie.Poster_Path);
                if (string.IsNullOrEmpty(movie.Poster_Path))//포스터 이미지 없으면 No_Picture 출력
                {
                    ImgPoster.Source = new BitmapImage(new Uri("/No_Picture.png", UriKind.RelativeOrAbsolute));
                }
                else//포스터 이미지 경로가 있으면
                {
                    var base_url = "https://image.tmdb.org/t/p/w300_and_h450_bestv2";
                    ImgPoster.Source = new BitmapImage(new Uri($"{base_url}{movie.Poster_Path}", UriKind.RelativeOrAbsolute));
                }
            }
            catch
            {

            }
        }

        private async void BtnWatchTrailer_Click(object sender, RoutedEventArgs e)
        {
            // 영화 예고편 Youtube에서 보기
            if(GrdResult.SelectedItems.Count==0)
            {
                await Commons.ShowMessageAsync("Youtube", "영화를 선택해주세요!");
                return;
            }
            if(GrdResult.SelectedItems.Count>1)
            {
                await Commons.ShowMessageAsync("Youtube", "영화를 하나만 선택해주세요!");
                return;
            }
            string movieName = string.Empty;
            var movie = GrdResult.SelectedItem as MovieItem; //영화의 모든 정보 
            movieName = movie.Title;
            //await Commons.ShowMessageAsync("유튜브", $"예고편 볼 영화 : {movieName}");
            var trailerWindow = new TrailerWindow(movieName);
            trailerWindow.Owner = this;//trailerwindow의 부모는 MainWindow
            trailerWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;//부모창 중앙에 위치
            trailerWindow.ShowDialog();//모달창으로 열기. show()로 모달리스로 열면 부모창 건드려짐
        }

        //즐겨찾기 저장
        private async void BtnAddFavorite_Click(object sender, RoutedEventArgs e)
        {
            if(GrdResult.SelectedItems.Count==0)
            {
                await Commons.ShowMessageAsync("오류", "즐겨찾기에 추가할 영화를 선택하세요(복수선택 가능)");
                return;
            }

            if(isFavorite)
            {
                await Commons.ShowMessageAsync("오류", "이미 즐겨찾기한 영화입니다");
                return;
            }

            List<FavoriteMovieItem> list = new List<FavoriteMovieItem>();
            foreach(MovieItem item in GrdResult.SelectedItems)
            {
                var favoriteMovie = new FavoriteMovieItem
                {
                    Id = item.Id,
                    Title = item.Title,
                    Original_Title = item.Original_Title,
                    Adult = item.Adult,
                    Overview = item.Overview,
                    Release_Date = item.Release_Date,
                    Original_Language = item.Original_Language,
                    Vote_Average = item.Vote_Average,
                    Popularity = item.Popularity,
                    Poster_Path = item.Poster_Path,
                    Reg_Date = DateTime.Now // 지금 저장하는 일시 생성
                };
                list.Add(favoriteMovie);
            }

            try
            {
                // DB 연결 확인
                using (SqlConnection conn = new SqlConnection(Commons.connString))
                {
                    if (conn.State == System.Data.ConnectionState.Closed) conn.Open();

                    var query = @"INSERT INTO [dbo].[FavoriteMovieItem]
                                           ([id]
                                           ,[Title]
                                           ,[Original_Title]
                                           ,[Realease_Date]
                                           ,[Original_Language]
                                           ,[Adult]
                                           ,[Popularity]
                                           ,[Vote_Average]
                                           ,[Poster_Path]
                                           ,[Overview]
                                           ,[Reg_Date])
                                     VALUES
                                           (@id
                                           ,@Title
                                           ,@Original_Title
                                           ,@Realease_Date
                                           ,@Original_Language
                                           ,@Adult
                                           ,@Popularity
                                           ,@Vote_Average
                                           ,@Poster_Path
                                           ,@Overview
                                           ,@Reg_Date)";
                    var insRes = 0; 
                    foreach(FavoriteMovieItem item in list)
                    {
                        SqlCommand cmd = new SqlCommand(query, conn);
                        cmd.Parameters.AddWithValue("@id", item.Id);
                        cmd.Parameters.AddWithValue("@Title", item.Title);
                        cmd.Parameters.AddWithValue("@Original_Title", item.Original_Title);
                        cmd.Parameters.AddWithValue("@Realease_Date", item.Release_Date);
                        cmd.Parameters.AddWithValue("@Original_Language", item.Original_Language);
                        cmd.Parameters.AddWithValue("@Adult", item.Adult);
                        cmd.Parameters.AddWithValue("@Popularity", item.Popularity);
                        cmd.Parameters.AddWithValue("@Vote_Average", item.Vote_Average);
                        cmd.Parameters.AddWithValue("@Poster_Path", item.Poster_Path);
                        cmd.Parameters.AddWithValue("@Overview", item.Overview);
                        cmd.Parameters.AddWithValue("@Reg_Date", item.Reg_Date);

                        insRes+=cmd.ExecuteNonQuery();
                    }
                    if(list.Count == insRes)
                    {
                        await Commons.ShowMessageAsync("저장", "DB 저장 성공");
                    }
                    else
                    {
                        await Commons.ShowMessageAsync("저장", "DB 저장 오류 관리자에게 문의하세요!");
                    }
                }
            }
            catch(Exception ex)
            {
                await Commons.ShowMessageAsync("오류", $"DB저장 오류 {ex.Message}");
            }
        }
    }
}
  • 포스터 뿌려주기 및 DB 연결

TrailerWindow.xaml

<mah:MetroWindow x:Class="wpf11_MovieFinder.TrailerWindow"
        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:cefSharp ="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
        xmlns:local="clr-namespace:wpf11_MovieFinder"
        mc:Ignorable="d"
        Title="유튜브 예고편" Height="350" Width="800"
                 FontFamily="NanumGothic" Loaded="MetroWindow_Loaded"
                 Closing="MetroWindow_Closing">
    <mah:MetroWindow.IconTemplate>
        <DataTemplate>
            <iconPacks:PackIconModern Kind="Youtube" Foreground="White" Margin="5,7,0,0"/>
        </DataTemplate>
    </mah:MetroWindow.IconTemplate>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>

        <Label Grid.Row="0" Grid.Column="0" x:Name="LblMovieName" FontSize="14" Margin="10"
               Content="영화제목"/>

        <ListView Grid.Row="1" Grid.Column="0" x:Name="LsvResult" Margin="5" MouseDoubleClick="LsvResult_MouseDoubleClick">
            <ListView.View>
                <GridView>
                    <!--컬럼들 나열-->
                    <GridViewColumn Header="썸네일" Width="100">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Image Source="{Binding Thumbnail}"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="타이틀" Width="Auto"
                                    DisplayMemberBinding="{Binding Title}"/>
                    <!--<GridViewColumn Header="제작자" Width="Auto"
                                    DisplayMemberBinding="{Binding Author}"/>-->
                    <GridViewColumn Header="채널명" Width="Auto"
                                    DisplayMemberBinding="{Binding ChannelTitle}"/>
                    <GridViewColumn Header="링크" Width="Auto"
                                    DisplayMemberBinding="{Binding URL}"/>
                </GridView>
            </ListView.View>
        </ListView>

        <!--웹브라우저 영역-->
        <Grid Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Margin="10" Background="Gainsboro">
            <cefSharp:ChromiumWebBrowser x:Name="BrsYoutube" Address="https://www.youtube.com"/>
        </Grid>

    </Grid>
</mah:MetroWindow>

TrailerWindow.xaml.cs

using Google.Apis.Services;
using Google.Apis.YouTube.v3;
using MahApps.Metro.Controls;
using System;
using System.Collections.Generic;
using System.Diagnostics;
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.Shapes;
using wpf11_MovieFinder.Models;

namespace wpf11_MovieFinder
{
    /// <summary>
    /// TrailerWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class TrailerWindow : MetroWindow
    {
        List<YoutubeItem> youtubeItems = null; // 검색결과를 담을 리스트

        public TrailerWindow()
        {
            InitializeComponent();
        }
        //부모에서 데이터를 가져오려면 반드시 필요한 재정의 생성자
        public TrailerWindow(string movieName) : this()
        {
            LblMovieName.Content = $"{movieName} 예고편";
        }

        private void MetroWindow_Loaded(object sender, RoutedEventArgs e)
        {
            //화면 로드 완료 후 Youtube 실행
            youtubeItems = new List<YoutubeItem>();//초기화
            SearchYoutubeApi();
        }

        private async void SearchYoutubeApi()
        {
            await LoadDataCollection();
            LsvResult.ItemsSource = youtubeItems; // direct binding 
        }

        private async Task LoadDataCollection()
        {
            var youtubeService = new YouTubeService(
                new BaseClientService.Initializer()
                {
                    ApiKey = "AIzaSyCRs0FAqizh_j_LMqren845f3Bwrs4Nhk8",//구글에서 발급받은 youtube api key
                    ApplicationName = this.GetType().ToString()
                });
            var req = youtubeService.Search.List("snippet");
            req.Q = LblMovieName.Content.ToString();
            req.MaxResults = 10;

            var res = await req.ExecuteAsync(); //검색 결과를 받아옴

            Debug.WriteLine("유튜브 검색결과 ---");
            foreach (var item in res.Items)
            {
                Debug.WriteLine(item.Snippet.Title);
                if(item.Id.Kind.Equals("youtube#video"))//youtube#video만 플레이 
                {
                    YoutubeItem youtube = new YoutubeItem
                    {
                        Title = item.Snippet.Title,
                        ChannelTitle = item.Snippet.ChannelTitle,
                        URL = $"https://www.youtube.com/watch?v={item.Id.VideoId}" , //유튜브 플레이 링크
                        //Author = item.Snippet.ChannelTitle
                    };
                    youtube.Thumbnail = new BitmapImage(new Uri(item.Snippet.Thumbnails.Default__.Url,
                                                        UriKind.RelativeOrAbsolute));
                    youtubeItems.Add(youtube);
                }
            }
        }

        private void LsvResult_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if(LsvResult.SelectedItem is YoutubeItem)
            {
                var video = LsvResult.SelectedItem as YoutubeItem;
                BrsYoutube.Address = video.URL;
            }
        }

        private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            BrsYoutube.Address = string.Empty;//웹브라우저 주소 클리어
            BrsYoutube.Dispose();//리소스 해제
        }
        //부모에서 영화 객체를 통째로 전달
        //public TrailerWindow(MovieItem movie):this()
        //{
        //    LblMovieName.Content= $"{movie} 예고편";
        //}
    }
}

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
{
    public class Commons
    {
        // 연결 문자열 담을 변수
        public static readonly string connString = "Data Source=localhost;" +
                                                    "Initial Catalog=pknu;" +
                                                    "Persist Security Info=True;"+
                                                    "User ID=sa;"+
                                                    "Password=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);
        }
    }
}
  • connString은 연결 후 우측 솔루션 탐색기 하단에 나오는 속성 / 문자열을 참조할것

Models/FavoriteMovieItem.cs

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

namespace wpf11_MovieFinder.Models
{
    public class FavoriteMovieItem
    {
        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; }
        public DateTime Reg_Date { get; set; }
    }
}

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

Models/YoutubeItem.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;

namespace wpf11_MovieFinder.Models
{
    public class YoutubeItem
    {
        public string Title { get; set; }
        public string Author { get; set; }
        public string ChannelTitle { get; set; }
        public string URL { get; set; }
        public BitmapImage Thumbnail { get; set; }
    }
}

실행화면

Main 화면

영화 검색 후 데이터 그리드에서 영화 클릭

예고편 보기 Button 클릭

예고편 더블 클릭

--> 우측에 해당 예고편 재생

즐겨찾기 추가


--> SSMS의 FavoriteMovieItem DB에 선택하여 즐겨찾기에 추가한 영화인 존윅 4 삽입됨을 확인

0개의 댓글