Bing APIを使ってWeb検索とImage検索を実装する

2011年10月17日(月)
PROJECT KySS

次に、MainPage.xamlを展開して表示される、MainPage.xaml.vbをダブルクリックして、リスト3のコードを記述します。

ロジックコードを記述する

リスト3 (MainPage.xaml.vb)

Option Strict On
Imports System.Xml.Linq
Imports System.Net

WebInfoクラス内にTitle、Description、Urlのプロパティを定義しておきます。これは[Web検索]時に使用されます。
Public Class WebInfo
  Property Title As String
  Property Description As String
  Property Url As String
End Class

ImageInfoクラス内にTitle、MediaUrl、Urlのプロパティを定義しておきます。これは[Image検索]時に使用されます。
Public Class ImageInfo
  Property Title As String
  Property MediaUrl As String
  Property Url As String
End Class

Partial Public Class MainPage
  Inherits PhoneApplicationPage

  ' Constructor
  Public Sub New()
    InitializeComponent()
  End Sub

定数変数myAppIDを宣言し、値に「Bing Developer Center で取得したAppID」を指定します。
  Const AppID As String = "Bing Developer Center で取得したApplicationID"

Boolean型のメンバ変数flagを宣言します。
  Dim flag As Boolean = False

[OK]ボタンがクリックされた時の処理

webRadioButtonにチェックが付いている場合は、flagメンバ変数にFalseを指定します。
Setvalue メソッドで、ListBox(resultListBox) の ItemTemplateProperty に、Web 検索用として定義しておいた、WebListBoxTemplate を指定します。
API へのリクエストは、検索キーワードや検索対象ソースなどの条件を下記のような URL で指定します。(REST)
Dim myUri = String.Format("http://api.search.live.net/xml.aspx?Appid={0}&query={1}&sources=web&web.count=20", AppID, TextBox1.Text)
今回はWeb検索としますので、sourcesにwebと指定します。
このリクエストで返ってくる結果 XML には、web という接頭辞が付加されています(図10参照)ので、XNamespace オブジェクトを作成して文字列を割り当てます。これにより、名前空間とローカル名を結合できます。
新しいWebClientのインスタンスmyWebClientオブジェクトを生成します。DownloadStringAsyncメソッドで、Uri として指定したリソースをダウンロードします。
AddHandler メソッドでダウンロードが完了した DownloadStringCompleted イベントに、イベント ハンドラーを追加します。イベント ハンドラー内では、ダウンロードされた文字列としての結果 XML を、Parse メソッドで読み込みます。Descendants メソッドで、子孫要素である名前空間を結合した全ての <WebResult> 要素のコレクションに対して、各要素を変数 result に格納しながら、WebInfo クラスの「Title」、「Description」、「Url」プロパティに、名前空間を結合した、<Title>、< Description >、<Url> 要素の値を指定し、WebInfo クラスの新しいリストとして作成した、myWebInfo オブジェクトに追加していきます。
ListBox(resultListBox) の ItemSource プロパティに myWebInfo オブジェクトを指定すると、Webの検索結果が ListBox 内に表示されます。

次に「Image検索」ラジオボタンがチェックされた場合の処理です。
imageRadioButtonにチェックが付いている場合は、flagメンバ変数にTrueを指定します。
Setvalue メソッドで、ListBox(resultListBox) の ItemTemplateProperty に、Image 検索用として定義しておいた、ImageListBoxTemplate を指定します。
API へのリクエストは、検索キーワードや検索対象ソースなどの条件を下記のような URL で指定します。(REST)
Dim myUri = String.Format("http://api.search.live.net/xml.aspx?Appid={0}&query={1}&sources=image&web.count=20", AppID, TextBox1.Text)
今回はImage検索としますので、sourcesにimageと指定します。
このリクエストで返ってくる結果 XML には、mms という接頭辞が付加されています(図10参照)ので、XNamespace オブジェクトを作成して文字列を割り当てます。これにより、名前空間とローカル名を結合できます。
新しいWebClientのインスタンスmyWebClientオブジェクトを生成します。DownloadStringAsyncメソッドで、Uri として指定したリソースをダウンロードします。
AddHandler メソッドでダウンロードが完了した DownloadStringCompleted イベントに、イベント ハンドラーを追加します。イベント ハンドラー内では、ダウンロードされた文字列としての結果 XML を、Parse メソッドで読み込みます。Descendants メソッドで、子孫要素である名前空間を結合した全ての <ImageResult> 要素のコレクションに対して、各要素を変数 result に格納しながら、ImagebInfo クラスの「Title」、「MediaUrl」、「Url」プロパティに、名前空間を結合した、<Title>、< MediaUrl >、<Url> 要素の値を指定し、ImageInfo クラスの新しいリストとして作成した、myImageInfo オブジェクトに追加していきます。
ListBox(resultListBox) の ItemSource プロパティに myImageInfo オブジェクトを指定すると、Imageの検索結果が ListBox 内に表示されます。

  Private Sub Button1_Click(sender As Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
    If webRadioButton.IsChecked = True Then
      flag = False
      resultListBox.SetValue(ListBox.ItemTemplateProperty, Resources("WebListBoxTemplate"))
      Dim myUri = String.Format("http://api.search.live.net/xml.aspx?Appid={0}&query={1}&sources=web&web.count=20", AppID, TextBox1.Text)
      Dim webNS As XNamespace = "http://schemas.microsoft.com/LiveSearch/2008/04/XML/web"
      Dim myWebClient As New WebClient
      myWebClient.DownloadStringAsync(New Uri(myUri, UriKind.Absolute))
 
      AddHandler myWebClient.DownloadStringCompleted, Sub(resultdSender As Object, resultArgs As DownloadStringCompletedEventArgs)
        Dim xmldoc As XElement = XElement.Parse(resultArgs.Result)
        Dim myWebInfo As New List(Of WebInfo)
        For Each result In From c In xmldoc.Descendants(webNS + "WebResult") Select c
          With myWebInfo
            .Add(New WebInfo With {.Title = result.Element(webNS + "Title").Value,
              .Description = result.Element(webNS + "Description").Value,
              .Url = result.Element(webNS + "Url").Value})
            End With
        Next
          resultListBox.ItemsSource = myWebInfo
      End Sub
    Else
      flag = True
      resultListBox.SetValue(ListBox.ItemTemplateProperty, Resources("ImageListBoxTemplate"))
 
      Dim myUri = String.Format("http://api.search.live.net/xml.aspx?Appid={0}&query={1}&sources=image&web.count=20", AppID, TextBox1.Text)
      Dim mmsNS As XNamespace = "http://schemas.microsoft.com/LiveSearch/2008/04/XML/multimedia"
      Dim myWebClient As New WebClient
      myWebClient.DownloadStringAsync(New Uri(myUri, UriKind.Absolute))
 
      AddHandler myWebClient.DownloadStringCompleted, Sub(resultSender As Object, resultArgs As DownloadStringCompletedEventArgs)
          Dim xmldoc As XElement = XElement.Parse(resultArgs.Result)
 
            Dim myImageInfo As New List(Of ImageInfo)
      For Each result In From c In xmldoc.Descendants(mmsNS + "ImageResult") Select c
        With myImageInfo
          .Add(New ImageInfo With {.Title = result.Element(mmsNS + "Title").Value,
              .MediaUrl = result.Element(mmsNS + "MediaUrl").Value,
              .Url = result.Element(mmsNS + "Url").Value})
        End With
      Next
        resultListBox.ItemsSource = myImageInfo
    End Sub
  End If
End Sub

ListBox に表示された検索結果の項目が選択された時の処理

ブール型メンバ変数で条件分岐を行います。flag が False の時、つまり「Web 検索」にチェックが付いている場合は、ListBox(resultListBox) より選択された項目を WebInfo クラスにキャストし、「Url」プロパティの値を取得します。この値を引数にして、WebBrowserPage.xaml に遷移します。
    
flag が True の時、つまり「Image 検索」にチェックが付いている場合は、ListBox(resultListBox) より選択された項目を ImageInfo クラスにキャストし、「Url」プロパティの値を取得します。この値を引数にして、WebBrowserPage.xaml に遷移します。
    
Try~Catch~End Tryステートメントで例外処理を行っておいてください。この処理を怠るとエミュレータのBack(←)ボタンで戻った場合エラーが表示されます。
  Private Sub resultListBox_SelectionChanged(sender As Object, e As System.Windows.Controls.SelectionChangedEventArgs) Handles resultListBox.SelectionChanged
    Try
      Dim myUrl As String = String.Empty
      If flag = False Then
        myUrl = DirectCast(resultListBox.SelectedItem, WebInfo).Url
      Else
        myUrl = DirectCast(resultListBox.SelectedItem, ImageInfo).Url
      End If
      
      NavigationService.Navigate(New Uri("/WebBrowserPage.xaml?uri=" & myUrl, UriKind.Relative))
    Catch
      Exit Sub
    End Try
  End Sub
End Class

次に、WebBrowserPage.xamlを展開して、WebBrowserPage.xaml.vbをダブルクリックして、リスト4のコードを記述します。

ロジックコードを記述する

リスト4 (WebBrowserPage.xaml.vb)

Option Strict On
Partial Public Class WebBrowserPage
  Inherits PhoneApplicationPage
 
  Public Sub New()
    InitializeComponent()
  End Sub

ページが読み込まれた時の処理

ここで、Mainpage..xamlから渡された文字データを受け取ります。文字データはNavigationContextのQueryStringにDictionary として提供されます。WebBrowser1.Navigateメソッドで引数として渡されたサイトに遷移します。WebBrowser内に指定したサイトが表示されます。
  Private Sub WebBrowserPage_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    Dim param As IDictionary(Of String, String) = NavigationContext.QueryString
    WebBrowser1.Navigate(New Uri(param("uri"), UriKind.Absolute))
  End Sub

エミュレータのBack(←)ボタンを上書きする処理

NavigationService.GoBack()メソッドで、エントリが存在する場合は、"戻る" ナビゲーション履歴の最新のエントリに移動します
  Protected Overrides Sub OnBackKeyPress(e As System.ComponentModel.CancelEventArgs)
    NavigationService.GoBack()
    MyBase.OnBackKeyPress(e)
  End Sub
End Class
  • 「Bing APIを使ってWeb検索とImage検索を実装する」サンプルプログラム

四国のSOHO。薬師寺国安(VBプログラマ)と、薬師寺聖(デザイナ、エンジニア)によるコラボレーション・ユニット。1997年6月、Dynamic HTMLとDirectAnimationの普及を目的として結成。共同開発やユニット名義での執筆活動を行う。XMLおよび.NETに関する著書や連載多数。最新刊は「Silverlight実践プログラミング」両名とも、Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。http://www.PROJECTKySS.NET/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています