Xamarin.Forms 地圖釘選

Download Sample 下載範例

控制項 Xamarin.FormsMap 允許使用 物件標記 Pin 位置。 Pin是點選時開啟資訊視窗的地圖示記:

Screenshot of a map pin and its information window, on iOS and Android

Pin當物件加入至集合時Map.Pins,圖釘會在地圖上轉譯。

類別 Pin 具有下列屬性:

  • Addressstring別為 的 ,這通常代表針腳位置的位址。 不過,它可以是任何 string 內容,而不只是位址。
  • Labelstring別為 的 ,通常代表釘選標題。
  • PositionPosition別為 的 ,表示針腳的緯度和經度。
  • TypePinType別為 的 ,表示針腳的類型。

這些屬性是由 BindableProperty 物件所支援,這表示 Pin 可以是數據系結的目標。 如需數據系結 Pin 對象的詳細資訊,請參閱 顯示釘選集合

此外,類別 PinMarkerClicked 定義和 InfoWindowClicked 事件。 點 MarkerClicked 選釘選時會引發事件,並在 InfoWindowClicked 點選資訊視窗時引發事件。 PinClickedEventArgs同時同時伴隨這兩個事件的物件具有單HideInfoWindow一屬性,類型為 bool

顯示釘選

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 會 Map 建立 物件,以顯示 物件所 MapSpan 指定的區域。 此 MapSpan 物件是以 物件表示 Position 的緯度和經度為中心,其會延伸0.01緯度和經度度。 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 屬性會導致ArgumentException在 新增至 MapPin擲回 。

此範例程式代碼會導致在地圖上轉譯單一釘選:

Screenshot of a map pin, on iOS and Android

與釘選互動

根據預設, Pin 點選時會顯示其資訊視窗:

Screenshot of a map pin and its information window, on iOS and Android

點選地圖上的其他地方會關閉信息視窗。

類別 PinMarkerClicked 定義事件,該事件會在點選 時 Pin 引發。 不需要處理此事件,才能顯示信息視窗。 相反地,當需要通知特定針腳已點選時,應該處理此事件。

類別 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同時同時伴隨這兩個事件的物件具有單HideInfoWindow一屬性,類型為 bool。 當這個屬性設定為 true 事件處理程式內時,將會隱藏信息視窗。

釘選類型

Pin 物件包含 Type 類型的 PinType屬性,代表針腳的類型。 PinType 列舉會定義下列成員:

  • Generic,表示泛型針腳。
  • Place,表示位置的釘選。
  • SavedPin,表示儲存位置的釘選。
  • SearchResult,表示搜尋結果的釘選。

不過,將 Pin.Type 屬性設定為任何 PinType 成員並不會變更轉譯釘選的外觀。 相反地,您必須建立自定義轉譯器來自定義釘選外觀。 如需詳細資訊,請參閱 自定義地圖釘選。

顯示 PIN 集合

類別 Map 會定義下列屬性:

重要

設定 ItemTemplateItemTemplateSelector 屬性時ItemTemplate,屬性會優先使用。

Map可以使用資料系結將其ItemsSource屬性系結至IEnumerable集合,以釘選填入 :

<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連接的 viewmodel 屬性,該屬性會ObservableCollectionLocation傳回 物件的 ,這是自定義型別。 每個Location物件都會Address定義 型string別 的 和 Description 屬性,以及 Position 型別 Position的屬性。

集合中 IEnumerable 每個項目的外觀都是藉由將 屬性設定 ItemTemplateDataTemplatePin ,其中包含數據系結至適當屬性之 物件的 。

下列螢幕快照顯示 Map 使用資料系結來 Pin 顯示集合:

Screenshot of map with data bound pins, on iOS and Android

選擇運行時間的項目外觀

您可以藉由將 屬性設定ItemTemplateSelectorDataTemplateSelector,在執行時間根據專案值選擇集合中IEnumerable每個項目的外觀:

<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;
    }
}

類別 MapItemTemplateSelectorDefaultTemplate 定義 和 XamarinTemplateDataTemplate 屬性,這些屬性會設定為不同的數據範本。 當專案具有包含 「San Francisco」 的位址時,此方法 OnSelectTemplateXamarinTemplate傳回 ,當點選 時 Pin ,會將 「Xamarin」 顯示為標籤。 當項目沒有包含 「San Francisco」 的位址時, OnSelectTemplate 此方法會傳 DefaultTemplate回 。

注意

這項功能的使用案例是根據Pin子類型,將子類別Pin對象的屬性系結至不同的屬性。

如需數據範本選取器的詳細資訊,請參閱 建立 Xamarin.Forms DataTemplateSelector