Série „Vývoj desktopové mapové aplikace“Číslo5. díl.
Tentokrátv 4. dílupřidáme do vytvořené mapové aplikace funkci zobrazování jednotlivých atributů dat, která jsou na mapě zobrazena. Ukázkový kód funkcí představených v tomto článku je zveřejněn na Esriジャパン GitHub .
Zobrazení jednotlivých atributů
Implementujeme funkci, která zobrazuje atributové informace vybranéhoprvku (feature), aby bylo možné zjistit, jaké hodnoty tento prvek obsahuje. Tentokrát si ukážeme atributy polygonu školních obvodů základních a středních škol nebo bodů základních a středních škol, na které na mapě klepnete.
1. Otevřete MainWindows.xaml a implementujte událostGeoViewTapped (přidejte GeoViewTapped="MainMapView_GeoViewTapped").
MainWindows.xaml
<esri:MapView x:Name="MainMapView" Map="{Binding Map, Source={StaticResource MapViewModel}}" GeoViewTapped="MainMapView_GeoViewTapped"/>
2. Otevřete MainWindows.xaml.cs a přidejte následující using direktivy.
MainWindows.xaml.cs
using Esri.ArcGISRuntime.Data;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.UI.Controls;
using Esri.ArcGISRuntime.UI;
3. Vytvořte zpracování události GeoViewTapped. Pro získání prvků na klepnutém místě použijte metodu
GeoView.IdentifyLayerAsync()Tato metoda přijímá vrstvu k identifikaci a souřadnice klepnutí ve screen bodech z události a vrací prvky ležící na klepnutém místě v dané vrstvě.
Pro vytvoření uživatelského rozhraní pro zobrazení atributů použijeme komponentu Callout (bublinu). Pomocí Callout lze snadno zobrazit bublinu na libovolném místě mapy.Metoda GeoView.ShowCalloutAt() přijímá pozici zobrazení (klepnuté místo) a obsah (CalloutDefinition) a zobrazí bublinu.MainWindows.xaml.cs// Handler události klepnutí na mapupublic async void MainMapView_GeoViewTapped(object sender, GeoViewInputEventArgs e){ // Skryjeme již zobrazený callout MainMapView.DismissCallout(); // Získáme souřadnice klepnutí ve screen bodech Point tapScreenPoint = e.Position; // Získáme souřadnice klepnutí v mapových souřadnicích
MapPoint tapMapPoint = e.Location!;
// Tolerance identifikace v pixelech kolem klepnutého bodu (čtverec s touto šířkou a výškou)
int pixelTolerance = 1;
// Určuje, zda se mají vracet pouze pop-up objekty (false = vrací i prvky)
var returnPopupsOnly = false;
// Identifikujeme vrstvy obsahující prvky v klepnutém místě a získáme výsledky identifikace
IReadOnlyList<IdentifyLayerResult> identifyLayerResults = await MainMapView.IdentifyLayersAsync(tapScreenPoint, pixelTolerance, returnPopupsOnly);
var currentMapViewModel = (MapViewModel)this.FindResource("MapViewModel");
// Vytvoříme obsah calloutu podle výsledků identifikace
CalloutDefinition? calloutDefinition = currentMapViewModel.Identify(identifyLayerResults);
// Zobrazíme callout na mapě, pokud existuje obsah k zobrazení
if (calloutDefinition != null)
{
MainMapView.ShowCalloutAt(tapMapPoint, calloutDefinition);
}
}
Tip: Druhý argument metody IdentifyLayerAsync určuje oblast identifikace jako čtverec se středem v klepnutém bodě o nastavené šířce a výšce v pixelech. Čím větší hodnota, tím širší oblast je identifikována, menší hodnota znamená užší oblast.
4. V souboru MapViewModel.cs vytvoříme metodu definující obsah pro Callout (CalloutDefinition) a také zvýraznění vybraných prvků.
'IdentifyLayersAsync()' vrací objekty typu 'GeoElement', které obsahují atributy i geometrii nalezených prvků.
'GeoElement' použijeme k vytvoření formátovaného 'CalloutDefinition'.
}
}
Tips: IdentifyLayerAsync メソッドに渡す第2引数には、識別する範囲を渡します。タップ地点を中心として、設定したスクリーン座標値の高さおよび幅を持つ正方形が識別範囲です。この値が大きいとタップ地点からより広い範囲を識別し、値が小さいと識別される範囲は狭くなります。
4. MapViewModel.cs に、Callout に表示するコンテンツ(CalloutDefinition)を定義する処理と取得されたフィーチャをハイライト表示する処理を作成します。IdentifyLayersAsync() を実行すると、該当するフィーチャの属性とジオメトリが含まれる GeoElement が返ります。GeoElement に含まれるフィーチャの属性情報を整形して CalloutDefinition を作成します。
MapViewModel.cs
public class MapViewModel : INotifyPropertyChanged
{
private Feature? _selectedFeature;
private FeatureLayer? _selectedLayer;
///中略///
public CalloutDefinition Identify(IReadOnlyList<IdentifyLayerResult> identifyLayerResults)
{
CalloutDefinition? calloutDefinition = null;
try
{
// 既に選択されている(ハイライト表示されている)フィーチャの選択を解除する
if (_selectedFeature != null) {
_selectedLayer!.UnselectFeature(_selectedFeature);
}
if (identifyLayerResults.Count == 0 || identifyLayerResults[0].GeoElements.Count == 0) {
throw new Exception("フィーチャが見つかりません");
}
// IdentifyLayersAsync() で取得したフィーチャを選択する(ハイライト表示する)
_selectedFeature = (Feature)identifyLayerResults[0].GeoElements[0];
_selectedLayer = (FeatureLayer)identifyLayerResults[0].LayerContent;
_selectedLayer.SelectFeature(_selectedFeature);
// レイヤーの属性情報のフィールド名とエイリアスを取得する
// Key にフィールド名、Value にフィールドのエイリアスを格納したディクショナリを作成する
var fields = new Dictionary<string, string>();
for (int i = 0; i < _selectedLayer.FeatureTable!.Fields.Count; i++) {
Field? field = _selectedLayer.FeatureTable.Fields[i];
fields.Add(field.Name, field.Alias);
}
// コールアウトのコンテンツ(タイトル)を設定する
string layerName = _selectedLayer.Name;
// 該当フィーチャの全ての属性情報を結合した文字列を作成する
var attributes = new System.Text.StringBuilder();
if (_selectedFeature.Attributes.Count > 0)
{
foreach (var attribute in _selectedFeature.Attributes) {
// 該当フィールドのエイリアスを取得する(attribute.Key はフィールド名)
string fieldName = fields[attribute.Key];
// 該当フィールドのフィールド値を取得する
object fieldValue = attribute.Value!;
attributes.AppendLine(fieldName + ": " + fieldValue);
}
attributes.AppendLine();
}
// コールアウトのコンテンツを定義する CalloutDefinition を作成する
calloutDefinition = new CalloutDefinition(layerName, attributes.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "エラー");
}
return calloutDefinition!;
}
Tips: 選択したフィーチャをハイライトしたいときには FeatureLayer.SelectFeature()を使用します。このメソッドに渡されたフィーチャがハイライト表示されます。
5. アプリを実行して任意の地点をクリックしてみましょう。クリック地点上にフィーチャがある場合、コールアウトが表示され属性情報を確認できます。
第5弾「個別属性表示」ではマップに追加されているデータの属性情報を表示する方法を紹介しました。次回、第6弾ではデバイスの現在地をマップ上に表示する方法を紹介します。
関連リンク