Windows Phoneの地図と位置データ


まず、Windows Phoneのマップへのインターフェイスを提供するマップコントロールから始めます。 Windows Phoneアプリケーションテンプレートから新しいプロジェクトを作成し、ExploreMapControlという名前を付けましょう。

プロジェクトが作成されたら、それが参照するライブラリを確認します。

次に、最小化されている場合はツールボックスを展開し、Mapコントロールをアプリケーションインターフェイスのデザイナーにドラッグします。



プロジェクトがMicrosoft.Phone.Controls.Mapを参照するようになりました。



MainPage.xamlページをダブルクリックして、XAMLコードの変更点を確認します。 私の名前空間からマップコントロールが追加されました。
<my:Map Height="50" HorizontalAlignment="Left" Margin="201,198,0,0" Name="map1" VerticalAlignment="Top" Width="100" /> 

XAMLドキュメントのタイトルを見ると、この名前空間が何であるかがわかります。
 xmlns:my="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps" 

名前空間名がその内容と一致するように、myをmapに置き換えましょう。
 xmlns:map="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps" 


 <map:Map Height="50" HorizontalAlignment="Left" Margin="201,198,0,0" Name="map1" VerticalAlignment="Top" Width="100" /> 

MapコントロールのXAMLコードを編集するか、Properitesパネルを使用して、要素が空き領域の大部分を占めるようにし、要素の名前をMyMapに変更します。
 <map:Map Name="MyMap"/> 


アプリケーション(F5)を起動し、実行時にコントロールがどのように見えるかを確認します。



ログインの詳細が間違っていることを示す白いバナーが画面中央に表示されていますか? これは、このコントロールがBingのマップサービスを使用し、それを使用するには登録が必要だからです。 キーを登録して、Bing Mapsポータル( http://www.bingmapsportal.com)で受け取ることができます
登録の最後に、開発者は文字列キーを受け取ります。これは、コントロール要素のCredentialsProviderプロパティで指定する必要があり、リソースまたはデータに転送することもできます。
シンプルなマップコントロールを追加します。ズームアウト/ズームアウト、マップ表示モードの変更。
 <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <map:Map Name="MyMap"> <Button Name="ZoomIn" Content="+" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="60" Width="60" Margin="-100,0,0,-5" Click="ZoomIn_Click" FontWeight="Bold" Padding="0,-9,0,0"/> <Button Name="ZoomOut" Content="-" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="60" Width="60" Margin="100,0,0,-5" Click="ZoomOut_Click" FontWeight="Bold" Padding="0,-9,0,0" /> <Button Name="LayoutChange" Content="L" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="60" Width="60" Margin="0,0,0,-5" FontWeight="Bold" Padding="0,-9,0,0" Click="LayoutChange_Click"/> </map:Map> </Grid> 

そして、これらのイベントをアプリケーションコードで処理します。
 private void ZoomIn_Click(object sender, RoutedEventArgs e) { MyMap.ZoomLevel += 1; } private void ZoomOut_Click(object sender, RoutedEventArgs e) { MyMap.ZoomLevel -= 1; } private void LayoutChange_Click(object sender, RoutedEventArgs e) { if (MyMap.Mode is RoadMode) { MyMap.Mode = new AerialMode(true); } else { MyMap.Mode = new RoadMode(); } } 

usingブロックに次のディレクティブを忘れずに追加してください。
 using Microsoft.Phone.Controls.Maps; 

アプリケーション(F5)を起動し、コントロールが意図したとおりに機能していることを確認します。 Metroの設計に従って、アプリケーションウィンドウの下部にあるボタンを備えたパネルをアプリケーションバーとして配置する必要がありますが、これは例を単純化するために、より単純なオプションを使用する場合のみです。 独立した演習として、ボタンを削除し、XAMLファイル内のサンプルアプリケーションバーコードのコメントを解除して、Metroスタイルに従ってアプリケーションを作り直すことができます。

次に、電話で利用できるジオロケーションサービスに移りましょう。 このサービスは、Wi-Fiから受信した情報、セルラー通信、GPS受信機からのデータの組み合わせを使用して情報を提供します。 ここで、ジオロケーションサービスによって提供される機能をアプリケーションに追加します。

まず、usingブロックに次のディレクティブを追加します。
 using Microsoft.Devices.Sensors; 

これで、ロケーション/ロケーションサービスを使用する準備が整いました。

最初に、プログラムから簡単な追加を作成します。これは、サービスから受信した地理位置情報データに従って地図を中央に配置します。
GeoCoordinateWatcher型の変数の定義をクラスに追加します。これにより、位置情報サービスを初期化し、それらからデータを取得できます。
 private GeoCoordinateWatcher myGeoWatcher; 

クラスコンストラクターで、加速度計に関連するコードの直後に、サービスステータス変更イベント(利用できない、準備ができていないなど)および位置変更イベントの初期化および登録コードを追加します。
 yGeoWatcher = new GeoCoordinateWatcher(); myGeoWatcher.MovementThreshold = 100.0f; myGeoWatcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(myGeoWatcher_StatusChanged); myGeoWatcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(myGeoWatcher_PositionChanged); 

優れたアプリケーションは、ジオサービスのステータスを正しく処理する必要があります。 データを常に生成できるわけではなく、初期化にかなりの時間を費やす可能性があります。 まず、エミュレータでアプリケーションをテストするため、ハンドラーを空のままにします。このような問題はありません。
また、アプリケーションの最初のバージョンでは、エミュレーターの使用を考慮に入れて、アプリケーションの読み込みを遅くしないように、位置情報サービスの起動を別のストリームに配置する方が適切です。クラスコンストラクターでサービスを起動します。
 myGeoWatcher.TryStart(false, TimeSpan.FromSeconds(60)); 

Visual StudioがStatusChangedおよびPositionChangedイベントハンドラーを自動的に生成した場合、NotImplemented例外を発生させるこれらのメソッドのコードをコメント化または削除します。
 throw new NotImplementedException(); 

PositionChangedイベントハンドラーで、位置を変更するときにマップを中央に配置するコードを追加します。
 void myGeoWatcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e) { MyMap.Center = e.Position.Location; } 


アプリケーション(F5)を起動し、エミュレーターの機能を使用して位置情報データをエミュレートし、プログラムの動作を確認します。 ズームインして、位置決めが正しく行われていることを確認します。


次のステップであるプログラムを改善するには、別のスレッドでサービスを起動し、位置情報データのステータスバーを追加し、地図上に位置を示すポイントを作成します。
スレッドを使用するには、次のディレクティブをusingブロックに追加します。
 using System.Threading; 

コンストラクターで、サービスを開始する前に、コードを追加します。
 new Thread(startMyGeoWotcher).Start(); 

その後、startMyGeoWotcherという名前の値を受け入れたり返したりしない関数を作成し、サービス起動コードをそこに転送します。
 void startMyGeoWotcher() { myGeoWatcher.TryStart(false, TimeSpan.FromSeconds(60)); } 

TextBlockコントロールを追加して、位置情報サービスのステータスを表示します
 <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel> <TextBlock Name="GeoStatus" HorizontalAlignment="Center" VerticalAlignment="Top" Text="Geo Status .." /> <map:Map Name="MyMap" Height="580"> <Button Name="ZoomIn" Content="+" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="60" Width="60" Margin="-100,0,0,-5" Click="ZoomIn_Click" FontWeight="Bold" Padding="0,-9,0,0"/> <Button Name="ZoomOut" Content="-" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="60" Width="60" Margin="100,0,0,-5" Click="ZoomOut_Click" FontWeight="Bold" Padding="0,-9,0,0" /> <Button Name="LayoutChange" Content="L" HorizontalAlignment="Center" VerticalAlignment="Bottom" Height="60" Width="60" Margin="0,0,0,-5" FontWeight="Bold" Padding="0,-9,0,0" Click="LayoutChange_Click"/> </map:Map> </StackPanel> </Grid> 

ステータス出力をStatusChangedハンドラーに追加します。
 void myGeoWatcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e) { switch (e.Status) { case GeoPositionStatus.Disabled: if (myGeoWatcher.Permission == GeoPositionPermission.Denied) { GeoStatus.Text = " "; } else { GeoStatus.Text = "    "; } break; case GeoPositionStatus.Initializing: GeoStatus.Text = " "; break; case GeoPositionStatus.NoData: GeoStatus.Text = "   "; break; case GeoPositionStatus.Ready: GeoStatus.Text = "   "; break; } } 

最後に、位置変更イベントハンドラーで、マップにポイント設定を追加します。
プッシュピン変数をクラスに追加します。
 private Pushpin myPushpin; 

クラスコンストラクターで作成しましょう。
 myPushpin = new Pushpin(); 

位置変更ハンドラーで、現在の位置に設定し、存在しない場合はマップに追加します。
 myPushpin.Location = e.Position.Location; if (!MyMap.Children.Contains(myPushpin)) MyMap.Children.Add(myPushpin); 

アプリケーション(F5)を起動し、エミュレーターの機能を使用して位置情報データをエミュレートし、プログラムの動作を確認します。 ズームインして、ポイントの位置と設定が正しいことを確認します。 ジオロケーションサービスの表示状態も確認してください。


UPD :コメントandrew_kaneに正しく記述されています。 プールのスレッドを使用するのがより適切な方法です。

以下は、プールのスレッドを操作するために変更する必要があり、呼び出す必要のないコードです
 new Thread(...).Start(); 

代わりに
 new Thread(startMyGeoWotcher).Start(); 

次のコードを記述する必要があります。
 ThreadPool.QueueUserWorkItem(startMyGeoWotcher, myGeoWatcher); 

プールを使用するには静的メソッドが必要であり、オブジェクトを静的にするか、パラメーターとして渡すかの2つのオプションがあるため、オブジェクトをメソッドに渡す必要があります。

今、あなたはメソッドを書き直す必要があります
 startMyGeoWotcher 
次のようになります。
 static void startMyGeoWotcher(object GeoWatcher) { ((GeoCoordinateWatcher)GeoWatcher).TryStart(false, TimeSpan.FromSeconds(60)); } 


便利なリンク:
MSDNのWindows Phone開発センター
Windows Phone SDK 7.1
ロシア語でのWindows Phone開発フォーラム

Source: https://habr.com/ru/post/J134239/


All Articles