Freigeben über


Xamarin.Forms Karten-Pins

Mit dem Xamarin.FormsMap-Steuerelement können Speicherorte mit Pin-Objekten markiert werden. Ein Pin ist eine Kartenmarkierung, die beim Antippen ein Informationsfenster öffnet:

Screenshot eines Kartennadels und seines Informationsfensters unter iOS und Android

Wenn ein Pin-Objekt zur Map.Pins-Sammlung hinzugefügt wird, wird die Stecknadel auf der Karte gerendert.

Die Pin-Klasse weist die folgenden Eigenschaften auf:

  • Address, vom Typ string, der in der Regel die Adresse für den Pinspeicherort darstellt. Es kann jedoch jeder string Inhalt sein, nicht nur eine Adresse.
  • Label, vom Typ string, der in der Regel den Pintitel darstellt.
  • Position, vom Typ Position, der den Breiten- und Längengrad des Pins darstellt.
  • Type, vom Typ PinType, der den Typ des Pins darstellt.

Diese Eigenschaften werden durch BindableProperty-Objekte unterstützt, was bedeutet, dass ein Pin das Ziel von Datenbindungen sein kann. Weitere Informationen zur Datenbindung Pin von Objekten finden Sie unter Anzeigen einer Pinsammlung.

Darüber hinaus definiert die Klasse Pin die Ereignisse MarkerClicked und InfoWindowClicked. Das MarkerClicked-Ereignis wird ausgelöst, wenn auf eine Pin getippt wird und das InfoWindowClicked-Ereignis ausgelöst wird, wenn auf das Informationsfenster getippt wird. Das PinClickedEventArgs-Objekt, das die beiden Ereignisse begleitet, hat eine einzige HideInfoWindow-Eigenschaft vom Typ bool.

Anzeigen einer Pin

Ein Pin kann zu einem Map in XAML hinzugefügt werden:

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

Erstellt ein neues Map-Objekt, das die von MapSpan angegebene Region anzeigt. Das MapSpan-Objekt wird auf dem Breiten- und Längengrad zentriert, das durch ein Position-Objekt dargestellt wird, das 0,01 Breiten- und Längengrad erweitert. Ein Pin-Objekt wird der Map.Pins-Sammlung hinzugefügt und auf dem Map an der durch seine Position-Eigenschaft angegebenen Stelle gezeichnet. Informationen zur Position Struktur finden Sie unter Kartenposition und Abstand. Informationen zum Übergeben von Argumenten in XAML an Objekte ohne Standardkonstruktoren finden Sie unter Übergeben von Argumenten in XAML.

Der entsprechende C#-Code lautet:

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

Warnung

Fehler beim Festlegen der Pin.Label Eigenschaft führt dazu, dass die ArgumentException Eigenschaft ausgelöst wird, wenn die Eigenschaft Pin einem Maphinzugefügt wird.

Dieser Beispielcode führt dazu, dass ein einzelner Pin auf einer Karte gerendert wird:

Screenshot eines Kartennadels unter iOS und Android

Interagieren mit Fragen und Antworten

Wenn auf ein Pin-Informationsfenster getippt wird, wird standardmäßig folgendes angezeigt:

Screenshot eines Kartennadels und seines Informationsfensters unter iOS und Android

Durch Tippen an einer anderen Stelle auf der Karte wird das Informationsfenster geschlossen.

Die Pin-Klasse definiert ein MarkerClicked-Ereignis, das ausgelöst wird, wenn ein Pin angetippt wird. Es ist nicht erforderlich, dieses Ereignis zu behandeln, um das Informationsfenster anzuzeigen. Stattdessen sollte dieses Ereignis behandelt werden, wenn eine Anforderung besteht, benachrichtigt zu werden, dass eine bestimmte Pin angetippt wurde.

Die Pin-Klasse definiert auch ein InfoWindowClicked-Ereignis, das ausgelöst wird, wenn auf ein Informationsfenster getippt wird. Dieses Ereignis sollte behandelt werden, wenn eine Anforderung besteht, benachrichtigt zu werden, dass auf ein bestimmtes Informationsfenster getippt wurde.

Der folgende Code zeigt ein Beispiel für die Behandlung dieser Ereignisse:

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

Das PinClickedEventArgs-Objekt, das die beiden Ereignisse begleitet, hat eine einzige HideInfoWindow-Eigenschaft vom Typ bool. Wenn diese Eigenschaft innerhalb eines Event-Handlers auf true gesetzt wird, wird das Informationsfenster ausgeblendet.

Pintypen

Pin-Objekte enthalten eine Type-Eigenschaft vom Typ PinType, die den Typ des Pins darstellt. Die PinType-Enumeration definiert die folgenden Members:

  • Generic, stellt einen generischen Benutzer dar.
  • Place, stellt einen Pin für eine Stelle dar.
  • SavedPin, stellt einen Pin für einen gespeicherten Speicherort dar.
  • SearchResult, stellt einen Pin für ein Suchergebnis dar.

Das Festlegen der Pin.Type-Eigenschaft auf ein PinType-Element ändert jedoch nicht die Darstellung der gerenderten Pin. Stattdessen müssen Sie einen benutzerdefinierten Renderer erstellen, um die Pindarstellung anzupassen. Weitere Informationen finden Sie unter Anpassen eines Kartennadels.

Anzeigen einer PIN-Sammlung

Die Map-Klasse definiert die folgenden Eigenschaften:

Wichtig

Die Eigenschaft ItemTemplate hat Vorrang, wenn sowohl die Eigenschaften ItemTemplate als auch ItemTemplateSelector festgelegt sind.

Ein Map kann mit Pins bestückt werden, indem seine ItemsSource-Eigenschaft mittels Datenbindung an eine IEnumerable-Sammlung gebunden wird:

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

Die ItemsSource-Eigenschaftsdaten sind an die Locations-Eigenschaft des verbundenen Viewmodels gebunden, das ein ObservableCollection-Objekt von Location zurückgibt, das ein benutzerdefinierter Typ ist. Jedes Location-Objekt definiert Address- und Description-Eigenschaften vom Typ string und eine Position-Eigenschaft vom Typ Position.

Das Aussehen jedes Elements in der IEnumerable-Sammlung wird definiert, indem die ItemTemplate-Eigenschaft auf ein DataTemplate gesetzt wird, das ein Pin-Objekt enthält, das mit den entsprechenden Eigenschaften verknüpft ist.

Die folgenden Screenshots zeigen eine MapPin Sammlung mit Datenbindung:

Screenshot der Karte mit datengebundenen Pins, unter iOS und Android

Auswählen der Elementdarstellung zur Laufzeit

Das Aussehen jedes Elements in der IEnumerable-Sammlung kann zur Laufzeit auf der Grundlage des Elementwerts ausgewählt werden, indem die ItemTemplateSelector-Eigenschaft auf ein DataTemplateSelector gesetzt wird:

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

Im folgenden Beispiel wird die MapItemTemplateSelector-Klasse gezeigt.

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

Die Klasse MapItemTemplateSelector definiert DefaultTemplate und XamarinTemplateDataTemplate Eigenschaften, die auf verschiedene Datenvorlagen gesetzt werden. Die OnSelectTemplate-Methode gibt das XamarinTemplate zurück, das „Xamarin“ als Beschriftung anzeigt, wenn ein Pin angetippt wird und das Element eine Adresse hat, die „San Francisco“ enthält. Wenn das Objekt keine Adresse hat, die „San Francisco“ enthält, gibt die Methode OnSelectTemplate den Wert DefaultTemplate zurück.

Hinweis

Ein Appsfall für diese Funktionalität ist die Bindung von Eigenschaften von Pin-Objekten der Unterklassen an verschiedene Eigenschaften, basierend auf dem Pin-Subtyp.

Weitere Informationen zu Datenvorlagenselektoren finden Sie unter Creating a Xamarin.Forms DataTemplateSelector.