Xamarin.Forms マップ ピン

Xamarin.FormsMap コントロールを使用すると、場所を Pin オブジェクトでマークできます。 Pin は、タップしたときに情報ウィンドウを開くマップ マーカーです。

iOS および Android 上のマップ ピンとその情報ウィンドウのスクリーンショット

Pin オブジェクトを Map.Pins コレクションに追加すると、ピンがマップ上にレンダリングされます。

Pin クラスには次のプロパティがあります。

  • string 型の Address は、通常はピンの場所のアドレスを表します。 ただし、アドレスだけでなく、任意の string のコンテンツも表すことができます。
  • string 型の Label は、通常はピンのタイトルを表します。
  • Position 型の Position は、ピンの緯度と経度を表します。
  • PinType 型の Type は、ピンの種類を表します。

BindableProperty オブジェクトはこれらのプロパティをサポートするので、Pin はデータ バインディングの対象になる場合があります。 データ バインディング Pin オブジェクトの詳細については、「ピンコレクションを表示する」をご覧ください。

さらに、Pin クラスが MarkerClickedInfoWindowClicked イベントを定義します。 MarkerClicked イベントはピンをタップしたときに発生し、InfoWindowClicked イベントは情報ウィンドウをタップしたときに発生します。 どちらのイベントにも付随する PinClickedEventArgs オブジェクトには、bool 型の HideInfoWindow プロパティが 1 つあります。

ピンを表示する

Pin は XAML で Map に追加できます。

<ContentPage ...
             xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps">
     <maps:Map x:Name="map"
               IsShowingUser="True"
               MoveToLastRegionOnLayoutChange="False">
         <x:Arguments>
             <maps:MapSpan>
                 <x:Arguments>
                     <maps:Position>
                         <x:Arguments>
                             <x:Double>36.9628066</x:Double>
                             <x:Double>-122.0194722</x:Double>
                         </x:Arguments>
                     </maps:Position>
                     <x:Double>0.01</x:Double>
                     <x:Double>0.01</x:Double>
                 </x:Arguments>
             </maps:MapSpan>
         </x:Arguments>
         <maps:Map.Pins>
             <maps:Pin Label="Santa Cruz"
                       Address="The city with a boardwalk"
                       Type="Place">
                 <maps:Pin.Position>
                     <maps:Position>
                         <x:Arguments>
                             <x:Double>36.9628066</x:Double>
                             <x:Double>-122.0194722</x:Double>
                         </x:Arguments>
                     </maps:Position>
                 </maps:Pin.Position>
             </maps:Pin>
         </maps:Map.Pins>
     </maps:Map>
</ContentPage>

XAML は、MapSpan オブジェクトで指定する領域を示す Map オブジェクトを作成します。 MapSpan オブジェクトは、緯度と経度の 0.01 度を拡張する Position オブジェクトで表す緯度と経度を中心にしています。 Pin オブジェクトを Map.Pins コレクションに追加し、その Position プロパティで指定した場所で Map に描画します。 Position 構造体については、マップの位置と距離に関する記事をご覧ください。 既定のコンストラクターがないオブジェクトに XAML で引数を渡す方法については、「XAML での引数の受け渡し」を参照してください。

同等の C# コードを次に示します。

using Xamarin.Forms.Maps;
// ...
Map map = new Map
{
  // ...
};
Pin pin = new Pin
{
  Label = "Santa Cruz",
  Address = "The city with a boardwalk",
  Type = PinType.Place,
  Position = new Position(36.9628066, -122.0194722)
};
map.Pins.Add(pin);

警告

Pin.Label プロパティの設定に失敗すると、PinMap に追加されたときに、ArgumentException がスローされます。

このコード例では、1 つのピンがマップにレンダリングされます。

iOS および Android 上のマップ ピンのスクリーンショット

ピンを操作する

既定では、Pin をタップすると、情報ウィンドウが表示されます。

iOS および Android 上のマップ ピンとその情報ウィンドウのスクリーンショット

マップ上の別の場所をタップすると、情報ウィンドウが閉じます。

Pin クラスは、Pin をタップしたときに発生する MarkerClicked イベントを定義します。 このイベントを処理して情報ウィンドウを表示する必要はありません。 代わりに、特定のピンがタップされたことを通知する必要がある場合は、このイベントを処理する必要があります。

Pin クラスは、情報ウィンドウをタップしたときに発生する InfoWindowClicked イベントも定義します。 このイベントは、特定の情報ウィンドウがタップされたことを通知する必要がある場合に処理する必要があります。

次のコードは、これらのイベント処理の例を示しています。

using Xamarin.Forms.Maps;
// ...
Pin boardwalkPin = new Pin
{
    Position = new Position(36.9641949, -122.0177232),
    Label = "Boardwalk",
    Address = "Santa Cruz",
    Type = PinType.Place
};
boardwalkPin.MarkerClicked += async (s, args) =>
{
    args.HideInfoWindow = true;
    string pinName = ((Pin)s).Label;
    await DisplayAlert("Pin Clicked", $"{pinName} was clicked.", "Ok");
};

Pin wharfPin = new Pin
{
    Position = new Position(36.9571571, -122.0173544),
    Label = "Wharf",
    Address = "Santa Cruz",
    Type = PinType.Place
};
wharfPin.InfoWindowClicked += async (s, args) =>
{
    string pinName = ((Pin)s).Label;
    await DisplayAlert("Info Window Clicked", $"The info window was clicked for {pinName}.", "Ok");
};

どちらのイベントにも付随する PinClickedEventArgs オブジェクトには、bool 型の HideInfoWindow プロパティが 1 つあります。 このプロパティがイベント ハンドラー内で true に設定されている場合、情報ウィンドウは非表示になります。

ピンの種類

Pin オブジェクトには PinType 型の Type プロパティが含まれていて、ピンの種類を表しています。 PinType 列挙型には、次のメンバーが定義されています。

  • Generic は、ジェネリック ピンを表します。
  • Place は、場所のピンを表します。
  • SavedPin は、保存された場所のピンを表します。
  • SearchResult は、検索結果のピンを表します。

ただし、Pin.Type プロパティを任意の PinType メンバーに設定しても、レンダリングしたピンの外観は変更されません。 代わりに、カスタム レンダラーを作成して、ピンの外観をカスタマイズする必要があります。 詳しくは、「マップ ピンのカスタマイズ」を参照してください。

Pin コレクションを表示する

Map クラスには、次のプロパティが定義されています。

重要

たとえば、ItemTemplateItemTemplateSelector の両方のプロパティを設定した場合、ItemTemplate プロパティが優先されます。

データ バインディングを使用して ItemsSource プロパティを IEnumerable コレクションにバインドすることで、Map にピンを設定できます。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
             x:Class="WorkingWithMaps.PinItemsSourcePage">
    <Grid>
        ...
        <maps:Map x:Name="map"
                  ItemsSource="{Binding Locations}">
            <maps:Map.ItemTemplate>
                <DataTemplate>
                    <maps:Pin Position="{Binding Position}"
                              Address="{Binding Address}"
                              Label="{Binding Description}" />
                </DataTemplate>
            </maps:Map.ItemTemplate>
        </maps:Map>
        ...
    </Grid>
</ContentPage>

ItemsSource プロパティ データは、接続されたビューモデルの Locations プロパティにバインドし、カスタム型である Location オブジェクトの ObservableCollection を返します。 各 Location オブジェクトは string 型の AddressDescription プロパティ、および Position 型の Position プロパティを定義します。

IEnumerable コレクション内の各項目の外観は、ItemTemplate プロパティを DataTemplate (データが適切なプロパティにバインドする Pin オブジェクトを含む) に設定することで定義します。

次のスクリーンショットは、データ バインディングを使用して Pin コレクションを表示する Map を示しています。

iOS および Android 上のデータ バインドされたピンを含むマップのスクリーンショット

実行時に項目の外観を選択する

IEnumerable コレクション内の各項目の外観は、実行時に項目の値に基づいて、ItemTemplateSelector プロパティを DataTemplateSelector に設定することで選択できます。

<ContentPage ...
             xmlns:local="clr-namespace:WorkingWithMaps"
             xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps">
    <ContentPage.Resources>
        <local:MapItemTemplateSelector x:Key="MapItemTemplateSelector">
            <local:MapItemTemplateSelector.DefaultTemplate>
                <DataTemplate>
                    <maps:Pin Position="{Binding Position}"
                              Address="{Binding Address}"
                              Label="{Binding Description}" />
                </DataTemplate>
            </local:MapItemTemplateSelector.DefaultTemplate>
            <local:MapItemTemplateSelector.XamarinTemplate>
                <DataTemplate>
                    <!-- Change the property values, or the properties that are bound to. -->
                    <maps:Pin Position="{Binding Position}"
                              Address="{Binding Address}"
                              Label="Xamarin!" />
                </DataTemplate>
            </local:MapItemTemplateSelector.XamarinTemplate>    
        </local:MapItemTemplateSelector>
    </ContentPage.Resources>

    <Grid>
        ...
        <maps:Map x:Name="map"
                  ItemsSource="{Binding Locations}"
                  ItemTemplateSelector="{StaticResource MapItemTemplateSelector}" />
        ...
    </Grid>
</ContentPage>

次の例は、MapItemTemplateSelector クラスを示しています。

public class MapItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate DefaultTemplate { get; set; }
    public DataTemplate XamarinTemplate { get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {
        return ((Location)item).Address.Contains("San Francisco") ? XamarinTemplate : DefaultTemplate;
    }
}

MapItemTemplateSelector クラスは、異なるデータ テンプレートに設定される DefaultTemplate および XamarinTemplate DataTemplate プロパティを定義します。 OnSelectTemplate メソッドは、項目に "San Francisco" を含むアドレスがある場合に、Pin をタップするとラベルとして "Xamarin" を表示する XamarinTemplate を返します。 項目に "San Francisco" を含むアドレスがない場合、OnSelectTemplate メソッドは DefaultTemplate を返します。

Note

この機能のユース ケースは、Pin サブタイプに基づいて、サブクラス化された Pin オブジェクトのプロパティを異なるプロパティにバインドすることです。

データ テンプレート セレクターの詳細については、「Xamarin.Forms DataTemplateSelector の作成」を参照してください。