Xamarin.Forms 맵Xamarin.Forms Map

샘플 다운로드 샘플 다운로드Download Sample Download the sample

Xamarin.Forms는 각 플랫폼에서 기본 지도 Api를 사용합니다.Xamarin.Forms uses the native map APIs on each platform.

Xamarin.Forms.Maps 각 플랫폼에 기본 지도 Api를 사용합니다.Xamarin.Forms.Maps uses the native map APIs on each platform. 이를 통해 사용자는 빠르고 친숙 한 지도를 제공할 수 있지만 각 플랫폼 API 요구 사항을 준수 하려면 몇 가지 구성 단계가 필요 합니다.This provides a fast, familiar maps experience for users, but means that some configuration steps are needed to adhere to each platforms API requirements. 한 번 구성 하면는 Map 공용 코드의 다른 모든 Xamarin.Forms 요소 처럼 작동을 제어 합니다.Once configured, the Map control works just like any other Xamarin.Forms element in common code.

지도 컨트롤에서 사용 된 합니다 MapsSample 아래 나와 있는 샘플입니다.The map control has been used in the MapsSample sample, which is shown below.

MobileCRM 예제의 mapsMaps in the MobileCRM sample

맵 기능을 만들어 더 향상 시킬 수 있습니다는 사용자 지정 렌더러를 매핑할합니다.Map functionality can be further enhanced by creating a map custom renderer.

맵 초기화Map initialization

Xamarin.Forms 응용 프로그램에 맵을 추가 하는 경우 Xamarin.Forms.Maps 솔루션의 모든 프로젝트에 추가 해야 하는 별도 NuGet 패키지입니다.When adding maps to a Xamarin.Forms application, Xamarin.Forms.Maps is a separate NuGet package that you should add to every project in the solution. Android에서이 또한에 종속이 되어 GooglePlayServices (다른 NuGet) Xamarin.Forms.Maps를 추가 하면 자동으로 다운로드 됩니다.On Android, this also has a dependency on GooglePlayServices (another NuGet) which is downloaded automatically when you add Xamarin.Forms.Maps.

NuGet 패키지를 설치한 후 초기화 코드를 각 응용 프로그램 프로젝트에서 필요 한 후Xamarin.Forms.Forms.Init 메서드 호출 합니다.After installing the NuGet package, some initialization code is required in each application project, after the Xamarin.Forms.Forms.Init method call. IOS에 대 한 다음 코드를 사용 합니다.For iOS use the following code:

Xamarin.FormsMaps.Init();

Android에서 동일한 매개 변수를 전달 해야 Forms.Init:On Android you must pass the same parameters as Forms.Init:

Xamarin.FormsMaps.Init(this, bundle);

다음 코드를 사용 하는 유니버설 Windows 플랫폼 (UWP)에 대 한 합니다.For the Universal Windows Platform (UWP) use the following code:

Xamarin.FormsMaps.Init("INSERT_AUTHENTICATION_TOKEN_HERE");

각 플랫폼에 대해 다음 파일에이 호출을 추가 합니다.Add this call in the following files for each platform:

  • iOS -AppDelegate.cs 파일을 FinishedLaunching 메서드.iOS - AppDelegate.cs file, in the FinishedLaunching method.
  • Android -MainActivity.cs 파일은 OnCreate 메서드.Android - MainActivity.cs file, in the OnCreate method.
  • UWP -MainPage.xaml.cs 파일을 MainPage 생성자입니다.UWP - MainPage.xaml.cs file, in the MainPage constructor.

NuGet 패키지를 추가 하 고 각 응용 프로그램 내에서 초기화 메서드를 호출 하면 Xamarin.Forms.Maps 일반적인 .NET Standard 라이브러리 프로젝트 또는 공유 프로젝트 코드에서 api를 사용할 수 있습니다.Once the NuGet package has been added and the initialization method called inside each application, Xamarin.Forms.Maps APIs can be used in the common .NET Standard library project or Shared Project code.

플랫폼 구성Platform configuration

지도 표시 되기 전에 일부 플랫폼에서 추가 구성 단계가 필요 합니다.Additional configuration steps are required on some platforms before the map will display.

iOSiOS

에 다음 키를 설정 해야 하는 iOS에서 위치 서비스에 액세스 하려면 Info.plist:To access location services on iOS, you must set the following keys in Info.plist:

IOS 11 및 이전 버전을 지원 하려면 모든 세 개의 키를 포함할 수 있습니다: NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, 및 NSLocationAlwaysUsageDescription합니다.To support iOS 11 and earlier, you can include all three keys: NSLocationWhenInUseUsageDescription, NSLocationAlwaysAndWhenInUseUsageDescription, and NSLocationAlwaysUsageDescription.

이러한 키에 대 한 XML 표현을 Info.plist 아래에 표시 됩니다.The XML representation for these keys in Info.plist is shown below. 업데이트 해야 합니다 string 응용 프로그램 위치 정보를 사용 하는 방식을 반영 하도록 값:You should update the string values to reflect how your application is using the location information:

<key>NSLocationAlwaysUsageDescription</key>
<string>Can we use your location at all times?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Can we use your location when your app is being used?</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Can we use your location at all times?</string>

합니다 Info.plist 항목에 추가할 수도 있습니다 원본 편집 하는 동안 보기의 Info.plist 파일:The Info.plist entries can also be added in Source view while editing the Info.plist file:

Ios 8 Info.plistInfo.plist for iOS 8

AndroidAndroid

사용 하는 Google Maps API v2 Android에서 API 키를 생성 한 Android 프로젝트에 추가 해야 합니다.To use the Google Maps API v2 on Android you must generate an API key and add it to your Android project. Xamarin 문서에서 지침에 따라 v2 Google Maps API 키를 가져오는합니다.Follow the instructions in the Xamarin doc on obtaining a Google Maps API v2 key. 이러한 지침에서는 뒤에 있는 API 키를 붙여 넣습니다. 합니다 Properties/AndroidManifest.xml 파일 (소스 보기 및 다음 요소 찾기/업데이트):After following those instructions, paste the API key in the Properties/AndroidManifest.xml file (view source and find/update the following element):

<application ...>
    <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR_API_KEY" />
</application>

유효한 API 키를 사용 하지 않으면 지도 컨트롤이 Android에서 회색 상자로 표시 됩니다.Without a valid API key the maps control will display as a gray box on Android.

참고

Google Maps에 액세스할 APK에 대 한 순서로 sha-1 지문 포함 하며 APK에 서명 하는 데 사용 하는 모든 keystore (디버그 및 릴리스)에 대 한 이름을 패키지 note 합니다.Note that, in order for your APK to access Google Maps, you must include SHA-1 fingerprints and package names for every keystore (debug and release) that you use to sign your APK. 예를 들어, 디버그 및 릴리스 APK를 생성 하기 위한 다른 컴퓨터에 대 한 컴퓨터를 사용 하는 경우 포함 해야 첫 번째 컴퓨터의 디버그 키 저장소에서 sha-1 인증서 지문 및의 릴리스 키 저장소에서 sha-1 인증서 지문 두 번째 컴퓨터입니다.For example, if you use one computer for debug and another computer for generating the release APK, you should include the SHA-1 certificate fingerprint from the debug keystore of the first computer and the SHA-1 certificate fingerprint from the release keystore of the second computer. 또한 경우 키 자격 증명을 편집 해야 앱의 패키지 이름을 변경 합니다.Also remember to edit the key credentials if the app's Package Name changes. 참조 v2 Google Maps API 키를 가져오는합니다.See obtaining a Google Maps API v2 key.

Android 프로젝트를 마우스 오른쪽 단추로 클릭 하 고 선택 하 여 적절 한 권한을 사용 하도록 설정 해야 옵션 > 빌드 > Android 응용 프로그램 다음 타이머에서 틱 및:You'll also need to enable appropriate permissions by right-clicking on the Android project and selecting Options > Build > Android Application and ticking the following:

  • AccessCoarseLocation
  • AccessFineLocation
  • AccessLocationExtraCommands
  • AccessMockLocation
  • AccessNetworkState
  • AccessWifiState
  • Internet

그 중 일부는 아래 스크린샷에 표시 됩니다.Some of these are shown in the screenshot below:

Android에 필요한 권한Required permissions for Android

마지막 두는 응용 프로그램 맵 데이터를 다운로드 하려면 네트워크 연결이 필요 하기 때문에 필요 합니다.The last two are required because applications require a network connection to download map data. Android에 대해 알아보세요 권한을 에 대해 자세히 알아보세요.Read about Android permissions to learn more.

또한 Android 9는 bootclasspath에서 Apache HTTP 클라이언트 라이브러리를 제거 했으므로 API 28 이상을 대상으로 하는 응용 프로그램에서는 사용할 수 없습니다.In addition, Android 9 has removed the Apache HTTP client library from the bootclasspath, and so it isn't available to applications that target API 28 or higher. API 28 이상을 대상으로 하는 응용 application 프로그램에서 Apache HTTP 클라이언트를 계속 사용 하려면 다음 줄을 androidmanifest .xml 파일의 노드에 추가 해야 합니다.The following line must be added to the application node of your AndroidManifest.xml file to continue using the Apache HTTP client in applications that target API 28 or higher:

<application ...>
    ...
    <uses-library android:name="org.apache.http.legacy" android:required="false" />    
</application>

UWPUniversal Windows Platform

유니버설 Windows 플랫폼에서 지도 사용 하 여 권한 부여 토큰을 생성 해야 합니다.To use maps on the Universal Windows Platform you must generate an authorization token. 자세한 내용은 지도 인증 키를 요청 MSDN에서.For more information, see Request a maps authentication key on MSDN.

인증 토큰을 다음으로 지정 해야 합니다 FormsMaps.Init("AUTHORIZATION_TOKEN") 메서드 호출에서 Bing Maps를 사용 하 여 앱을 인증 합니다.The authentication token should then be specified in the FormsMaps.Init("AUTHORIZATION_TOKEN") method call, to authenticate the app with Bing Maps.

맵 구성Map configuration

참조 된 MapPage.cs MobileCRM 샘플 코드의 맵 컨트롤을 사용할 수 있는 방법을의 예입니다.See the MapPage.cs in the MobileCRM sample for an example of how the map control can be used in code. 간단한 MapPage 클래스-이 알림은 다음과 같을 수 있습니다 하는 새 MapSpan 지도의 보기를 배치 하기 위해 만들어집니다.A simple MapPage class might look like this - notice that a new MapSpan is created to position the map's view:

public class MapPage : ContentPage {
    public MapPage() {
        var map = new Map(
            MapSpan.FromCenterAndRadius(
                    new Position(37,-122), Distance.FromMiles(0.3))) {
                IsShowingUser = true,
                HeightRequest = 100,
                WidthRequest = 960,
                VerticalOptions = LayoutOptions.FillAndExpand
            };
        var stack = new StackLayout { Spacing = 0 };
        stack.Children.Add(map);
        Content = stack;
    }
}

지도 유형Map type

맵 내용을 설정 하 여 변경할 수도 있습니다는 MapType 일반 거리 맵 (기본값), 위성 이미지 또는 둘의 조합을 표시할 속성입니다.The map content can also be changed by setting the MapType property, to show a regular street map (the default), satellite imagery or a combination of both.

map.MapType = MapType.Street;

유효한 MapType 값은:Valid MapType values are:

  • Hybrid
  • Satellite
  • Street (기본값)Street (the default)

지도 영역 및 MapSpanMap region and MapSpan

위의 코드 조각에서와 같이 제공을 MapSpan 초기 보기를 설정 하는 맵 생성자에는 인스턴스 (중심점 및 확대/축소 수준) 로드 되는 경우 맵의 합니다.As shown in the code snippet above, supplying a MapSpan instance to a map constructor sets the initial view (center point and zoom level) of the map when it is loaded. 두 가지 방법으로 새 MapSpan 인스턴스:There are two ways to create a new MapSpan instance:

  • MapSpan.FromCenterAndRadius() -의 범위를 만드는 정적 메서드를를 Position 지정 하는 Distance 합니다.MapSpan.FromCenterAndRadius() - static method to create a span from a Position and specifying a Distance .
  • 새 MapSpan () -사용 하는 생성자를 Position 위도 및 경도 표시할 각도입니다.new MapSpan () - constructor that uses a Position and the degrees of latitude and longitude to display.

MoveToRegion 지도의 위치 또는 확대/축소 수준을 변경 하려면 다음 map 클래스에서 메서드를 사용할 수 있습니다.The MoveToRegion method on the map class can then be used to change the position or zoom level of the map. 위치를 변경 하지 않고 지도의 확대/축소 수준을 변경 하려면 새로 만듭니다 MapSpan 에서 현재 위치를 사용 하는 VisibleRegion.Center 지도 컨트롤의 속성입니다.To change the zoom level of the map without altering the location, create a new MapSpan using the current location from the VisibleRegion.Center property of the map control. Slider 다음과 같이 지도 확대/축소를 제어 하는 데 사용할 수 있습니다. 그러나 지도 컨트롤에서 바로 확대/축소는 현재 슬라이더의 값을 업데이트할 수 없습니다.A Slider can be used to control map zoom like this (however zooming directly in the map control cannot currently update the value of the slider):

Slider slider = new Slider (1, 18, 1);
slider.ValueChanged += (sender, e) =>
{
    var zoomLevel = e.NewValue; // between 1 and 18
    var latlongdegrees = 360 / (Math.Pow(2, zoomLevel));
    map.MoveToRegion(new MapSpan (map.VisibleRegion.Center, latlongdegrees, latlongdegrees));
};

확대/축소를 사용 하 여 mapsMaps with zoom

또한 클래스에 Map 는 바인딩 가능한 속성에 의해 지원 bool되는 형식의 MoveToLastRegionOnLayoutChange 속성이 있습니다.In addition, the Map class has a MoveToLastRegionOnLayoutChange property of type bool, which is backed by a bindable property. 기본적으로이 속성은 true입니다 .이 속성은 표시 된 지도 지역이 장치 회전과 같은 레이아웃 변경이 발생할 때 현재 영역에서 이전 집합 영역으로 이동 함을 나타냅니다.By default this property is true, which indicates that the displayed map region will move from its current region to its previously set region when a layout change occurs, such as on device rotation. 이 속성을로 false설정 하면 레이아웃 변경이 발생할 때 표시 되는 맵 지역이 가운데에 그대로 유지 됩니다.When this property is set to false, the displayed map region will remain centered when a layout change occurs. 다음 예제에서는이 속성을 설정 하는 방법을 보여 줍니다.The following example shows setting this property:

map.MoveToLastRegionOnLayoutChange = false;

지도 핀Map pins

위치를 사용 하 여 지도에 표시할 수 있습니다 Pin 개체입니다.Locations can be marked on the map with Pin objects.

var position = new Position(37,-122); // Latitude, Longitude
var pin = new Pin {
            Type = PinType.Place,
            Position = position,
            Label = "custom pin",
            Address = "custom detail info"
        };
map.Pins.Add(pin);

PinType는 다음 값 중 하나로 설정할 수 있습니다 .이 값은 플랫폼에 따라 핀이 렌더링 되는 방식에 영향을 줄 수 있습니다.PinType can be set to one of the following values, which may affect the way the pin is rendered (depending on the platform):

  • 제네릭Generic
  • 현재 위치Place
  • SavedPinSavedPin
  • SearchResultSearchResult

지도 클릭Map clicks

Map지도를 MapClicked 누를 때 발생 하는 이벤트를 정의 합니다.Map defines a MapClicked event that's fired when the map is tapped. 이벤트와 MapClicked 함께 제공 되는 Position Position MapClickedEventArgs 개체에는 형식의 이라는 단일 속성이 있습니다.The MapClickedEventArgs object that accompanies the MapClicked event has a single property named Position, of type Position. 이벤트가 발생 하면 Position 속성의 값이 탭 된 지도 위치로 설정 됩니다.When the event is fired, the value of the Position property is set to the map location that was tapped.

다음 코드 예제에서는 MapClicked 이벤트에 대 한 이벤트 처리기를 보여 줍니다.The following code example shows an event handler for the MapClicked event:

map.MapClicked += OnMapClicked;

void OnMapClicked(object sender, MapClickedEventArgs e)
{
    System.Diagnostics.Debug.WriteLine($"MapClick: {e.Position.Latitude}, {e.Position.Longitude}");
}

이 예제에서 이벤트 처리기 OnMapClicked 는 탭 맵 위치를 나타내는 위도 및 경도를 출력 합니다.In this example, the OnMapClicked event handler outputs the latitude and longitude that represents the tapped map location.

XAML에서 맵 만들기Create a Map in XAML

다음 예제와 같이 맵을 XAML로 만들 수도 있습니다.Maps can also be created in XAML, as shown in this example:

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
             x:Class="MapDemo.MapPage">
    <StackLayout VerticalOptions="StartAndExpand" Padding="30">
        <maps:Map x:Name="MyMap"
                  Clicked="OnMapClicked"
                  WidthRequest="320"
                  HeightRequest="200"                  
                  IsShowingUser="true"
                  MapType="Hybrid" />
    </StackLayout>
</ContentPage>

참고

추가 xmlns 네임 스페이스 정의는 xamarin.ios 컨트롤을 참조 하는 데 필요 합니다.An additional xmlns namespace definition is required to reference the Xamarin.Forms.Maps controls.

MapMapRegion 는에대한명명된참조를사용하여코드에서설정할수있습니다.PinsThe MapRegion and Pins can be set in code using the named reference for the Map:

MyMap.MoveToRegion(
    MapSpan.FromCenterAndRadius(
        new Position(37,-122), Distance.FromMiles(1)));

데이터 바인딩을 사용 하 여 맵으로 데이터 채우기Populate a Map with data using data binding

또한 Map 클래스는 다음 속성을 노출 합니다.The Map class also exposes the following properties:

  • ItemsSource– 표시 되는 항목 IEnumerable 의 컬렉션을 지정 합니다.ItemsSource – specifies the collection of IEnumerable items to be displayed.
  • ItemTemplate– 표시 된 DataTemplate 항목 컬렉션의 각 항목에 적용할를 지정 합니다.ItemTemplate – specifies the DataTemplate to apply to each item in the collection of displayed items.
  • ItemTemplateSelector– 런타임에 항목 DataTemplateSelector 에 대해를 DataTemplate 선택 하는 데 사용 되는를 지정 합니다.ItemTemplateSelector – specifies the DataTemplateSelector that will be used to choose a DataTemplate for an item at runtime.

참고

ItemTemplate ItemTemplate 속성이모두설정된경우속성이우선적ItemTemplateSelector 으로 적용 됩니다.The ItemTemplate property takes precedence when both the ItemTemplate and ItemTemplateSelector properties are set.

데이터 바인딩을 사용 하 여 ItemsSource 속성을 IEnumerable 컬렉션에 바인딩하면 데이터를 데이터로 채울 수있습니다.MapA Map can be populated with data by using data binding to bind its ItemsSource property to an IEnumerable collection:

<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"
                  MoveToLastRegionOnLayoutChange="false"
                  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 개체 ObservableCollectionLocation 을 반환 하는 연결 된 뷰 모델의 속성에 바인딩됩니다.The ItemsSource property data binds to the Locations property of the connected view model, which returns an ObservableCollection of Location objects, which is a custom type. Location 개체는 Address 형식의 Description 및속성과Position 형식의속성Position을정의합니다. stringEach Location object defines Address and Description properties, of type string, and a Position property, of type Position.

IEnumerable 컬렉션에 있는 각 항목의 모양은 해당 속성에 데이터를 바인딩하 ItemTemplatePin 개체를 DataTemplate 포함 하는로 설정 하 여 정의 됩니다.The appearance of each item in the IEnumerable collection is defined by setting the ItemTemplate property to a DataTemplate that contains a Pin object that data binds to appropriate properties.

다음 스크린샷에는 데이터 바인딩을 Map 사용 하 Pin 여 컬렉션을 표시 하는 방법을 보여 줍니다.The following screenshots show a Map displaying a Pin collection using data binding:

데이터 바인딩된 pin을 사용 하 여 [ 데이터 바인딩된 핀이 있는 Map의 스크린샷 및 ] (map-images/pins-itemssource-large.png#lightbox "데이터 바인딩된 pin을 사용 하는 맵")Screenshot of map with data bound pins, on iOS and Android

런타임에 항목 모양 선택Choose item appearance at runtime

ItemTemplateSelector 속성을로 설정하IEnumerable 여 항목 값을 기준으로 런타임에 컬렉션에 있는 각 항목의 모양을 선택할 수 있습니다. DataTemplateSelectorThe appearance of each item in the IEnumerable collection can be chosen at runtime, based on the item value, by setting the ItemTemplateSelector property to a 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>
                    <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 보여 줍니다.The following example shows the MapItemTemplateSelector class:

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 속성을 정의 합니다.The MapItemTemplateSelector class defines DefaultTemplate and XamarinTemplate DataTemplate properties that are set to different data templates. 이 메서드는 OnSelectTemplate 항목 XamarinTemplate에 "샌프란시스코"가 포함 된 주소가 있는 경우 "Xamarin"을 탭으로 표시 하는을 반환 합니다. PinThe OnSelectTemplate method returns the XamarinTemplate, which displays "Xamarin" as a label when a Pin is tapped, when the item has an address that contains "San Francisco". 항목에 "샌프란시스코"가 포함 된 주소가 없는 경우 메서드는 OnSelectTemplateDefaultTemplate반환 합니다.When the item doesn't have an address that contains "San Francisco", the OnSelectTemplate method returns the DefaultTemplate.

데이터 템플릿 선택기에 대 한 자세한 내용은 DataTemplateSelector 만들기를 참조 하세요.For more information about data template selectors, see Creating a Xamarin.Forms DataTemplateSelector.