HTTP通信と検索機能
今回はHTTP通信、検索等の機能を使ったサンプルを作成してみます。
HTTP通信用のサーバーは ATND の イベントサーチAPI(ATND BETA)を使わせてもらいます。
ATND API リファレンス
サンプルの仕様
サンプルは“分割アプリケーション”のテンプレートを元に作成します。
主な仕様は以下の通りです。
HTTP通信
まずHTTP通信部分を作成します。
ATND の API から色々な情報を取得できますが、今回は画面表示用にタイトル、イベント開催日時、開催会場、ブラウザ起動用に ATND の URL を使用しますので、これらの情報を保持するデータソースクラスを作成します。
public class EventDataItem : HttpTest.Common.BindableBase { public EventDataItem(string title, string started_at, string place, string event_url) { this._title = title; this._started_at = started_at; this._place = place; this._event_url = event_url; } private string _title = string.Empty; public string Title { get { return this._title; } set { this.SetProperty(ref this._title, value); } } private string _started_at = string.Empty; public string StartedAt { get { return this._started_at; } set { this.SetProperty(ref this._started_at, value); } } private string _place = string.Empty; public string Place { get { return this._place; } set { this.SetProperty(ref this._place, value); } } private string _event_url = string.Empty; public string EventUrl { get { return this._event_url; } set { this.SetProperty(ref this._event_url, value); } } } public sealed class EventDataSource { private ObservableCollection<EventDataItem> _items = new ObservableCollection<EventDataItem>(); public ObservableCollection<EventDataItem> Items { get { return this._items; } } public EventDataSource() { } }
作成したデータソースを使って画面を表示するためにデータテンプレートを作成します(ItemsPage.xaml に追加)。
<UserControl.Resources> <CollectionViewSource x:Name="itemsViewSource" Source="{Binding Items}"/> <DataTemplate x:Key="EventItemTemplate"> <Grid HorizontalAlignment="Left" Width="300" Height="80"> <StackPanel Background="{StaticResource ListViewItemOverlayBackgroundBrush}"> <TextBlock Text="{Binding Title}" Foreground="{StaticResource ListViewItemOverlayTextBrush}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,0"/> <TextBlock Text="{Binding StartedAt}" Foreground="{StaticResource ListViewItemOverlaySecondaryTextBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,0"/> <TextBlock Text="{Binding Place}" Foreground="{StaticResource ListViewItemOverlaySecondaryTextBrush}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/> </StackPanel> </Grid> </DataTemplate> </UserControl.Resources>
GridView の ItemTemplate も、上記で定義した EventItemTemplate を使うように変更します。
実際に通信を行う処理は ItemsPage.xaml.cs に以下のように追加します。
// 検索して画面に表示 public async void SearchData(string keyword) { // 指定された検索キーワードを使ってリクエストURLを生成 var sb = new StringBuilder(); sb.Append("http://api.atnd.org/events/?count=30&format=json"); if (!String.IsNullOrEmpty(keyword)) { sb.AppendFormat("&keyword={0}", keyword); } // リクエストを送信して結果文字列を取得 var client = new HttpClient(); client.MaxResponseContentBufferSize = 1024 * 1024 * 10; var result = await client.GetStringAsync(sb.ToString()); // レスポンスを解析して一覧に追加 var rootElement = Windows.Data.Json.JsonObject.Parse(result); var eventElements = rootElement.GetNamedArray("events"); foreach (var elem in eventElements) { var title = elem.GetObject().GetNamedString("title"); var started_at = elem.GetObject().GetNamedString("started_at"); var place = elem.GetObject().GetNamedString("place"); var event_url = elem.GetObject().GetNamedString("event_url"); var item = new EventDataItem(title, started_at, place, event_url); _source.Items.Add(item); } }
ATND の API に取得する最大個数とレスポンスの形式(json)を固定で指定し、検索文字列が渡された場合はキーワードとして追加で指定します。
実際の通信は HttpClient の GetStringAsync メソッドを使って行い、結果を解析してデータソースに追加します。
検索機能
次の検索機能や起動時の処理等を追加していきます。
検索機能は宣言が必要ですので、アプリケーションマニフェストの宣言に検索を追加します。
まず、起動時の処理を App.xaml.cs に追加します。
// 通常の起動処理 protected override void OnLaunched(LaunchActivatedEventArgs args) { var _rootFrame = new Frame(); _rootFrame.Navigate(typeof(ItemsPage), null); Window.Current.Content = _rootFrame; Window.Current.Activate(); } // 検索ペインでアプリが選択された場合の起動処理 protected override void OnSearchActivated(SearchActivatedEventArgs args) { base.OnSearchActivated(args); if (Window.Current.Content == null) { // 検索指示でアプリが起動された var _rootFrame = new Frame(); _rootFrame.Navigate(typeof(ItemsPage), args.QueryText); Window.Current.Content = _rootFrame; Window.Current.Activate(); } else { // 中断状態の時に検索指示 ((ItemsPage)((Frame)Window.Current.Content).Content).UpdateQuery(args.QueryText); } }
OnLaunched は通常の起動処理です。
OnSearchActivated は、このアプリがアクティブではない(起動していない or 中断状態)時に、検索ペインでアプリが選択された場合に呼び出されます。
起動していない状態で呼び出された場合は、通常と同じようにページを表示します。この時、パラメータとして検索文字列を渡します。
中断状態で呼び出された場合は既にページは作成されていますので、ページ側のメソッドを呼び出して更新します(更新に使う UpdateQuery メソッドは後でページ側に追加します)。
続いてページ側(ItemsPage.xaml.cs)にも処理を追加します。
private EventDataSource _source = new EventDataSource(); public ItemsPage() { this.InitializeComponent(); var searchPane = SearchPane.GetForCurrentView(); searchPane.QuerySubmitted += SearchPane_QuerySubmitted; } protected override void OnNavigatedTo(NavigationEventArgs e) { this.DefaultViewModel["Items"] = _source.Items; UpdateQuery(e.Parameter as string); } // アプリ動作中に検索文字列が渡された void SearchPane_QuerySubmitted(SearchPane sender, SearchPaneQuerySubmittedEventArgs args) { UpdateQuery(args.QueryText); } // クエリ文字列更新 public void UpdateQuery(string querytext) { _source.Items.Clear(); if (String.IsNullOrEmpty(querytext)) { pageTitle.Text = "イベント"; } else { pageTitle.Text = "イベント検索結果: " + querytext; } SearchData(querytext); }
更新処理として UpdateQuery メソッドを追加しています。
このメソッドは、タイトルを変更した後で通信処理を呼び出して画面を更新します。
UpdateQuery メソッドを呼び出すパターンは以下の三種類あります。
- 起動時の動作として OnNavigatedTo メソッド内から呼び出します。
- QuerySubmitted イベントのハンドラから呼び出します。このイベントはアプリがアクティブな状態の時に、検索ペインで検索文字列が確定された場合に呼び出されます。
- アプリが中断状態の時に検索が実行された場合は、App クラスから直接呼び出します。
これで、イベント表示や検索が行えるようになります。
ブラウザ起動
最後にブラウザ起動処理を追加します。
ItemsPage.xaml.cs の ItemView_ItemClick を以下のように書き換えます。
async void ItemView_ItemClick(object sender, ItemClickEventArgs e) { var item = e.ClickedItem as EventDataItem; if (item != null) { // イベントURLを指定してブラウザ起動 var opt = new LauncherOptions(); await Launcher.LaunchUriAsync(new Uri(item.EventUrl)); } }
表示されている項目をクリックすると、対応する URL がブラウザで表示されるようになります。