De serie "Desktop Kaartapplicatie Ontwikkeling"Deel7.
Deze keer voegen we een adreszoekfunctie toe aan de kaartapplicatie die we in deel6 hebben gemaakt. De voorbeeldcode van de functie die in dit artikel wordt geïntroduceerd, is beschikbaar op Esri Japan GitHub .
Adreszoekfunctie
ArcGIS Maps SDK for .NET biedt functies voor geocodering, waarmee je de locatie kunt verkrijgen die overeenkomt met een adresstring, en reverse geocodering, waarmee je het adres van een specifieke locatie kunt ophalen. Deze keer implementeren we een functie waarbij je een adres invoert in een tekstvak en de kaart zoomt naar de overeenkomstige locatie.Geocoding
1. In MapViewModel.cs maken we een nieuwe eigenschap genaamdGraphicsOverlays, dit is een collectie van GraphicsOverlay die grafische elementen bevat voor de zoekresultaten (symbolen voor adreslocaties en labels met adresstrings).
MapViewModel.cs
private GraphicsOverlayCollection? _graphicsOverlays;
public GraphicsOverlayCollection? GraphicsOverlays
{
get { return _graphicsOverlays; }
set
{
_graphicsOverlays = value;
OnPropertyChanged();
}
}
2. Open MainWindow.xaml en bind de eigenschap MapViewModel GraphicsOverlays aan het MapView-control (voeg GraphicsOverlays="{Binding GraphicsOverlays, Source={StaticResource MapViewModel}}" toe).
MainWindow.xaml:
<esri:MapView x:Name="MainMapView"
Map="{Binding Map, Source={StaticResource MapViewModel}}"
GraphicsOverlays="{Binding GraphicsOverlays, Source={StaticResource MapViewModel}}"
GeoViewTapped="MainMapView_GeoViewTapped"/>
3. Voeg in MapViewModel.cs in de functie SetupMap , code toe om een nieuwe GraphicsOverlay
};
this.GraphicsOverlays = graphicsOverlays;
// 住所検索用の LocatorTask を作成する
Uri _serviceUri = new Uri("https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer");
_geocoder = await LocatorTask.CreateAsync(_serviceUri);
}
4. MainWindow.xaml で住所を入力するテキスト ボックスを含んだ画面を作成します。
MainWindow.xaml
<Border HorizontalAlignment="Right" VerticalAlignment="Top" Background="White" BorderThickness="0.5" BorderBrush="Gray" Margin="10" Padding="10" Width="250">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontWeight="SemiBold" Text="住所を入力" TextAlignment="Center" />
<TextBox x:Name="SearchBox" Grid.Row="1" Grid.Column="0" Margin="0,5,5,0" Text="東京都千代田区平河町2-7-1"/>
<Button x:Name="SearchButton" Grid.Row="1" Grid.Column="1" Margin="0,5,0,0" Click="SearchButton_Click" Content="検索"/>
</Grid>
</Border>
5. MainWindow.xaml.cs に検索ボタンをクリックした時の処理を実装します。
MainWindow.xaml.cs
// 住所検索ボタンのクリック イベント ハンドラー
private async void SearchButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
var currentMapViewModel = (MapViewModel)this.FindResource("MapViewModel");
// テキストボックスの値を取得して、住所検索を実行する
MapPoint? addressPoint = await currentMapViewModel.SearchAddress(SearchBox.Text);
if (addressPoint != null) {
// 検索した住所にマップの表示位置を変更する
MainMapView.SetViewpoint(new Viewpoint(addressPoint, 20000));
}
}
6. MapViewModel.cs に住所検索の処理を実装します。ジオコーディングを実行する GeocodeAsync メソッドには、オプションで検索結果を細かく指定するためのパラメーター(GeocodeParameters)を設定できます。GeocodeAsync メソッドは、デフォルトで検索結果の候補の住所全て(最大50個まで)が、マッチ率が高い順で返されます。今回は、MaxResults プロパティを設定し検索結果として返される候補の住所を1個に制限しています。検索結果で返される情報の詳細については、こちらも併せてご参照ください。
MapViewModel.cs
public async Task<MapPoint> SearchAddress(string searchText)
{
MapPoint? addressLocation = null;
try {
// 既存の検索結果のグラフィックスを消去する
GraphicsOverlay? geocodeResultOverlay = this.GraphicsOverlays?.FirstOrDefault();
geocodeResultOverlay!.Graphics.Clear();
// テキストボックスの値が空か LocatorTask が無効の場合は、処理を中止する
if (String.IsNullOrWhiteSpace(searchText) || _geocoder == null) {
throw new Exception("検索文字列が空か、ジオコーダーが無効です");
}
// 検索結果を1つ(マッチ率が最も高い住所)だけに制限する、ジオコーディングのパラメーターを作成する
GeocodeParameters geocodeParameters = new GeocodeParameters();
geocodeParameters.MaxResults = 1;
//入力文字列からジオコーディングを実行しマッチする住所(住所文字列と位置)を取得する
IReadOnlyList<GeocodeResult> addresses = await _geocoder.GeocodeAsync(searchText, geocodeParameters);
// 検索結果が取得できない場合は処理を中止する
if (addresses.Count < 1) {
throw new Exception("一致する結果がありません");
}
// 住所の位置に表示するポイント シンボルを作成する
SimpleMarkerSymbol pointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Diamond, System.Drawing.Color.Red, 15);
// 住所文字列のテキスト シンボルを作成する
TextSymbol textSymbol = new TextSymbol(addresses.First().Label, System.Drawing.Color.Yellow, 15, Esri.ArcGISRuntime.Symbology.HorizontalAlignment.Center, Esri.ArcGISRuntime.Symbology.VerticalAlignment.Bottom);
textSymbol.HaloColor = System.Drawing.Color.Gray;
textSymbol.HaloWidth = 3;
textSymbol.OffsetY = 10;
// ポイントとテキスト シンボルからグラフィックを作成する
Graphic pointGraphic = new Graphic(addresses.First().DisplayLocation, pointSymbol);
Graphic textGraphic = new Graphic(addresses.First().DisplayLocation, textSymbol);
// GraphicsOverlay にグラフィックを追加する
geocodeResultOverlay.Graphics.Add(pointGraphic);
geocodeResultOverlay.Graphics.Add(textGraphic);
// マップを住所の位置にズームするためのポイントを返す
addressLocation = addresses.First().DisplayLocation;
}
catch (Exception ex) {
MessageBox.Show(ex.ToString(), "エラー");
}
return addressLocation!;
}
7. アプリを実行してみましょう。入力した住所にマップが移動し、住所テキストとシンボルがマップ上に表示されます。
第7弾「住所検索」では住所文字列から該当する位置を取得するジオコーディングの機能を実装する方法を紹介しました。次回、第8弾では概観図の作成方法を紹介します。
関連リンク