データ取得ロジックの実装
サンプルアプリで使用するオープンデータは、Microsoft Azure Mobile Service上で動作しているAED検索オープンデータを使用します 。
Imports System.Collections.ObjectModel Imports System.ComponentModel Imports System.Net Imports System.Runtime.CompilerServices Imports Newtonsoft.Json Namespace Models Public Class AedInfo Public Property Id As Long Public Property LocationName As String '/* 場所_地名【名称】*/ Public Property FullAddress As String '/* 住所_住所【住所】*/ Public Property Perfecture As String '/* 構造化住所_都道府県 */ Public Property City As String '/* 構造化住所_市区町村 */ Public Property AddressArea As String '/* 構造化住所_町名 */ Public Property AddressCode As String '/* 住所コード */ Public Property Latitude As Single '/* 緯度経度座標系_緯度 */ Public Property Longitude As Single '/* 緯度経度座標系_経度 */ Public Property FacilityId As String '/* 公共設備_ID */ Public Property FacilityName As String '/* 公共設備_名称 */ Public Property FacilityPlace As String '/* 公共設備_設置場所【設置場所】※受付横とか */ Public Property ScheduleDayType As String '/* 公共設備_利用可能時間【利用可能時間】 */ Public Property PhotoOfAedUrl As String '/* 公共設備_写真URL【写真】 */ Public Property FacilityNote As String '/* 公共設備_補足【補足】 */ Public Property LatLng As Point End Class Public Class TCity Public Property Perfecture As String '/* 構造化住所_都道府県 */ Public Property City As String '/* 構造化住所_市区町村 */ Private _Items = New ObservableCollection(Of AedInfo) Public Property Items As ObservableCollection(Of AedInfo) Get Return Me._Items End Get Set(value As ObservableCollection(Of AedInfo)) Me._Items = value End Set End Property End Class Public Class AedModel Implements INotifyPropertyChanged Public Sub New() End Sub Private _City = New TCity Public Property City As TCity Get Return Me._City End Get Set(value As TCity) Me._City = value OnPropertyChanged() End Set End Property Public Async Function SelectData(perfectureName As String, cityName As String) As Task Dim targetAeds = New ObservableCollection(Of AedInfo) Try Dim urlString = String.Format( "https://aed.azure-mobile.net/api/aedinfo/{0}/{1}/", perfectureName, cityName) Dim request = CType((WebRequest.Create(urlString)), HttpWebRequest) request.Method = "GET" request.ContentType = "application/x-www-form-urlencoded" Try Dim response = CType((Await request.GetResponseAsync()), HttpWebResponse) Dim responseDataStream = New System.IO.StreamReader(response.GetResponseStream()) Dim responseResult = responseDataStream.ReadToEnd() Dim json = JsonConvert.DeserializeObject(Of IEnumerable(Of AedInfo))(responseResult) Dim aeds = From item In json Order By item.FullAddress targetAeds = New ObservableCollection(Of AedInfo) For Each aed In aeds aed.LatLng = New Point(aed.Longitude, aed.Latitude) targetAeds.Add(aed) Next Catch ex As Exception OnFaild("NetworkError" + ex.Message) End Try Catch ex As Exception OnFaild("NetworkError" + ex.Message) Finally Me.City = New TCity With {.Perfecture = perfectureName, .City = cityName, .Items = targetAeds} End Try End Function Public Event Faild(sender As Object, e As String) Protected Sub OnFaild(line As String) RaiseEvent Faild(Me, line) End Sub Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged Protected Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) End Sub End Class End Namespace
C1Mapsコンポーネントの配置
ツールボックスからC1MapsコンポーネントをXAMLエディタ上にドラッグ&ドロップします。これだけで必要な参照設定が行われます。
画面デザイン
サンプル画面の構成は、左に地図、右に一覧表の2カラム構成になっていて、検索ボタンをクリックすると特定市区町村のAED情報を検索表示します。
: (中略) : <Grid Grid.Row="1" Margin="15,0,0,0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <StackPanel Grid.Column="0" Margin="20,0,20,0"> <Viewbox VerticalAlignment="Top" HorizontalAlignment="Left"> <Custom:C1Maps x:Name="C1Maps1" VerticalAlignment="Top" HorizontalAlignment="Left" Zoom="13" Width="480" Height="600"> <Custom:C1Maps.Resources> <DataTemplate x:Key="PinStyle"> <Custom:C1VectorPlacemark Fill="Red" Stroke="Red" LabelPosition="Top" Foreground="Red" GeoPoint="{Binding LatLng}" Geometry="M7.4166234,16.197001L13.…(中略)…z"> <Custom:C1VectorPlacemark.RenderTransform> <TransformGroup> <ScaleTransform ScaleX="0.5" ScaleY="0.5"/> <TranslateTransform Y="-20" X="-10"/> </TransformGroup> </Custom:C1VectorPlacemark.RenderTransform> </Custom:C1VectorPlacemark> </DataTemplate> </Custom:C1Maps.Resources> <Custom:C1Maps.Source> <Custom:VirtualEarthRoadSource ApplicationId="{x:Null}" /> </Custom:C1Maps.Source> <Custom:C1VectorLayer ItemsSource="{Binding City.Items}" ItemTemplate="{StaticResource PinStyle}" LabelVisibility="Visible"/> </Custom:C1Maps> </Viewbox> </StackPanel> : (中略) :
C1Mapsコンポーネントで緯度経度に合わせてマークを描画するには、
- 緯度経度が含まれたコレクションをItemsSourceプロパティにBindingする
- マーク描画用スタイルをItemTemplateに指定する
- マーク描画用スタイルの中で、C1VectorPlacemarkのGeoPointに緯度経度をBindingする
- マーク自体はC1VectorPlacemarkのGeometryで形を指定する
という手順で行います。
コードビハインド側でループを回して1点1点位置を指定して描画する必要はありません。
検索イベント時のコードの記述
MainPage.xamlのコードビハインド側に検索用のロジックを一部記載します。
Namespace Views Public NotInheritable Class MainPage Inherits Page : (中略) : Public Sub New() InitializeComponent() : (中略) : Me.DataContext = App.MainVM End Sub Private Async Sub NavigationHelper_LoadState(sender As Object, e As Common.LoadStateEventArgs) Try Await App.MainVM.GetItems("愛知県", "豊田市") SetCenterPos() Me.C1Maps1.Zoom -= 1 Me.C1Maps1.Zoom += 1 Catch ex As Exception End Try : (中略) : End Namespace
NavigationHelper_LoadStateプロシージャの中で、GetItemsメソッドによりデータを取得後にZoomプロパティに-1および+1を実行しているのは、強制的に再描画を発生させて正しく画面が表示されるようにするためです。これは本来不要な処理ですが、ComponentOne Studio 2014 v2では描画方法が変わったのか、このような操作を行わないとマークが画面に表示されません。
ここまでできたら、後はMainViewModelクラスを記述すれば出来上がりです。