Haritalar ve konuma genel bakış

Windows Uygulama SDK'sı ve WinUI 3 haritaları görüntülemek, kullanıcının konumunu algılamak ve coğrafi konumları ayarlamak için API'ler ve denetimler sağlar. Pinlerle etkileşimli haritalar gösteren uygulamalar oluşturmak, kullanıcının konumunu izlemek ve kullanıcı coğrafi bir alana girdiğinde veya buradan ayrıldığında eylemleri tetikleyen uygulamalar oluşturmak için bu özellikleri kullanın.

Bu makale, her bir özelliği tanıtır ve tek bir çalışan uygulamada MapControl, Geolocator ve GeofenceMonitor bileşenlerini bir araya getiren eksiksiz bir örnek içerir.

Haritaları MapControl ile görüntüleme

MapControl, Azure Haritalar tarafından desteklenen etkileşimli bir harita görüntüler. İşaretçiler ve katmanlar ekleyebilir, ayrıca sürükleme, yakınlaştırma ve tıklama gibi kullanıcı etkileşimlerine yanıt verebilirsiniz.

MapControl bir Azure Haritalar hesabı gerektirir. Hesap oluşturmak ve hizmet belirteci almak için bkz. Azure Haritalar hesabınızı yönetme.

Ayrıntılı kullanım yönergeleri için bkz. MapControl.

<MapControl x:Name="myMap"
            MapServiceToken="YOUR_AZURE_MAPS_TOKEN"
            Height="400" />

Note

UWP MapControl ve Windows. Services.Maps API'leri kullanım dışıdır ve Windows'in gelecekteki sürümlerinde kullanılamayabilir. WinUI 3 uygulamaları yukarıda açıklanan yeni MapControl'ü kullanmalıdır. Daha fazla bilgi için bkz. Kullanım dışı bırakılan özellikler için kaynaklar.

Kullanıcının konumunu algılama

Windows. Devices.Geolocation API'leri, cihazın coğrafi konumunu edinmenizi sağlar. Bu API'ler hem UWP hem de Windows Uygulama SDK'sı (WinUI 3) uygulamalarında çalışır. Şunları yapabilirsiniz:

Adım adım kılavuz için bkz. Kullanıcının konumunu alma.

Coğrafi sınırları ayarlayın

Geofence bir coğrafi sınırı tanımlar. Kullanıcı sınıra girdiğinde veya sınırdan çıktığında uygulamanız bildirim alır. Coğrafi konumlar konum tabanlı anımsatıcılar, uyarılar veya içerik teslimi için kullanışlıdır.

Coğrafi konumları oluşturma ve izleme yönergeleri için bkz. Coğrafi bölge ayarlama.

Konum özelliği ve gizlilik

Tüm konum API'leri, uygulamanızın paket bildiriminde bildirilen Konum özelliğini gerektirir. Konum verilerine erişmeden önce çalışma zamanında Geolocator.RequestAccessAsync'i de çağırmalısınız.

Windows, kullanıcılara Ayarlar > Gizlilik ve güvenlik > Konumu aracılığıyla hangi uygulamaların konumlarına erişebilecekleri üzerinde denetim sağlar. Uygulamanızın, kullanıcının konum erişimini reddeddiği veya iptal ettiği durumu işlemesi gerekir.

Tam örnek

Aşağıdaki örnek, MapControl, Geolocator ve GeofenceMonitor öğelerini tek bir WinUI 3 penceresinde bir araya getirir. Azure Haritalar anahtarı yapılandırılmamışsa, coğrafi konum ve coğrafi sınırlama çalışmaya devam ederken harita düzgün bir şekilde düşer.

Prerequisites

  • Windows Uygulama SDK'sı 2.2 veya üzeri
  • Harita kutucuklarını görüntülemek için gereken bir Azure Haritalar tuşu. Geçerli bir anahtar olmadan MapControl görüntülenir ancak boş bir harita gösterir.
  • Package.appxmanifest içinde bildirilen Konum cihaz özelliği:
<DeviceCapability Name="location" />

Uygulamayı çalıştırmadan önce Azure Haritalar anahtarınızı ortam değişkeni olarak ayarlayın:

$env:AZURE_MAPS_KEY = "your-key-here"

MainWindow.xaml

Sol tarafta düğmeler ve durum metni bulunan 300 piksellik bir denetim masası ve sağda bir MapControl denetim masası. Azure Haritalar anahtarı eksik olduğunda bir katman görünür.

<?xml version="1.0" encoding="utf-8" ?>
<Window
    x:Class="MapLocationDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Map Location Demo">
    <Window.SystemBackdrop>
        <MicaBackdrop />
    </Window.SystemBackdrop>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <TitleBar Title="Map Location Demo" />

        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="300" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <Grid Grid.Column="0" Margin="16" RowSpacing="12">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>

                <TextBlock Text="Location Demo" FontSize="20" FontWeight="Bold"/>
                <StackPanel Grid.Row="1" Spacing="8">
                    <Button x:Name="FindMeButton" Content="Find My Location"
                            Click="FindMeButton_Click" HorizontalAlignment="Stretch"/>
                    <Button x:Name="AddGeofenceButton" Content="Add Geofence Here"
                            Click="AddGeofenceButton_Click" HorizontalAlignment="Stretch"/>
                </StackPanel>
                <TextBlock x:Name="StatusText" Grid.Row="2"
                           Text="Click 'Find My Location' to begin." TextWrapping="Wrap"/>
                <ListView x:Name="EventLog" Grid.Row="3" Header="Event Log"/>
            </Grid>

            <Grid Grid.Column="1">
                <MapControl x:Name="MyMap" />
                <StackPanel x:Name="MapKeyMissing" Visibility="Collapsed"
                            HorizontalAlignment="Center" VerticalAlignment="Center"
                            Spacing="8">
                    <FontIcon Glyph="&#xE783;" FontSize="48"
                              HorizontalAlignment="Center"
                              Foreground="{ThemeResource SystemFillColorCautionBrush}" />
                    <TextBlock Text="Azure Maps key not configured"
                               FontSize="18" FontWeight="SemiBold"
                               HorizontalAlignment="Center" />
                    <TextBlock x:Name="MapKeyHint" TextWrapping="Wrap" MaxWidth="400"
                               HorizontalAlignment="Center" TextAlignment="Center"
                               Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
                </StackPanel>
            </Grid>
        </Grid>
    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Devices.Geolocation;
using Windows.Devices.Geolocation.Geofencing;

namespace MapLocationDemo;

public sealed partial class MainWindow : Window
{
    private Geolocator? _geolocator;
    private BasicGeoposition _lastPosition;
    private bool _mapAvailable;

    public MainWindow()
    {
        InitializeComponent();
        _mapAvailable = TryConfigureMap();
        GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;
    }

    // Read the Azure Maps key from an environment variable.
    // If missing, collapse the map and show an informational overlay.
    private bool TryConfigureMap()
    {
        var key = Environment.GetEnvironmentVariable("AZURE_MAPS_KEY");
        if (string.IsNullOrWhiteSpace(key))
        {
            MyMap.Visibility = Visibility.Collapsed;
            MapKeyMissing.Visibility = Visibility.Visible;
            MapKeyHint.Text = "Set the AZURE_MAPS_KEY environment variable "
                + "and restart.\nGeolocation and geofencing still work "
                + "without the map.";
            Log("Azure Maps key not found — map disabled");
            return false;
        }
        MyMap.MapServiceToken = key;
        return true;
    }

    private async void FindMeButton_Click(object sender, RoutedEventArgs e)
    {
        FindMeButton.IsEnabled = false;
        StatusText.Text = "Requesting location access...";

        var access = await Geolocator.RequestAccessAsync();
        if (access != GeolocationAccessStatus.Allowed)
        {
            StatusText.Text =
                "Location access denied. Check Settings > Privacy > Location.";
            FindMeButton.IsEnabled = true;
            return;
        }

        _geolocator = new Geolocator { DesiredAccuracyInMeters = 100 };
        try
        {
            var pos = await _geolocator.GetGeopositionAsync();
            var lat = pos.Coordinate.Point.Position.Latitude;
            var lon = pos.Coordinate.Point.Position.Longitude;
            _lastPosition = new BasicGeoposition
            {
                Latitude = lat, Longitude = lon
            };

            StatusText.Text =
                $"Location: {lat:F5}, {lon:F5}  ({pos.Coordinate.Accuracy:F0} m)";
            Log($"Position: {lat:F5}, {lon:F5}");

            if (_mapAvailable)
            {
                var pt = new Geopoint(_lastPosition);
                MyMap.Center = pt;
                MyMap.ZoomLevel = 15;

                var layer = new MapElementsLayer();
                layer.MapElements = new List<MapElement>
                {
                    new MapIcon { Location = pt }
                };
                MyMap.Layers.Clear();
                MyMap.Layers.Add(layer);
            }
        }
        catch (Exception ex) { StatusText.Text = $"Error: {ex.Message}"; }
        finally { FindMeButton.IsEnabled = true; }
    }

    private void AddGeofenceButton_Click(object sender, RoutedEventArgs e)
    {
        if (_lastPosition.Latitude == 0 && _lastPosition.Longitude == 0)
        {
            StatusText.Text = "Get your location first.";
            return;
        }

        var fence = new Geofence("MyGeofence",
            new Geocircle(_lastPosition, 200),
            MonitoredGeofenceStates.Entered | MonitoredGeofenceStates.Exited,
            false, TimeSpan.FromSeconds(5));
        GeofenceMonitor.Current.Geofences.Add(fence);

        StatusText.Text = $"Geofence added at "
            + $"{_lastPosition.Latitude:F5}, {_lastPosition.Longitude:F5}";
        Log("Geofence registered");
    }

    private void OnGeofenceStateChanged(
        GeofenceMonitor sender, object args)
    {
        var reports = sender.ReadReports();
        DispatcherQueue.TryEnqueue(() =>
        {
            foreach (var r in reports)
            {
                var msg = r.NewState switch
                {
                    GeofenceState.Entered => $"Entered: {r.Geofence.Id}",
                    GeofenceState.Exited  => $"Exited: {r.Geofence.Id}",
                    GeofenceState.Removed => $"Removed: {r.Geofence.Id}",
                    _ => null
                };
                if (msg != null) { StatusText.Text = msg; Log(msg); }
            }
        });
    }

    private void Log(string msg) =>
        EventLog.Items.Insert(0, $"[{DateTime.Now:HH:mm:ss}] {msg}");
}

Temel desenler

  • MapControlWindows Uygulama SDK'sı 1.6 ve sonraki sürümlerde yerleşiktir. MapServiceToken değerini Azure Haritalar anahtarınız olarak ayarlayın.
  • TryConfigureMap başlangıçta ortam değişkenini AZURE_MAPS_KEY denetler. Değişken boşsa, harita daralır ve sorunun nasıl giderileceğini açıklayan bir kaplama görünür — çökme yok, boş harita yok.
  • Package.appxmanifest içinde DeviceCapability Name="location" gereklidir; aksi takdirde Geolocator.RequestAccessAsync, Denied döndürür.
  • GeofenceMonitor.GeofenceStateChanged, arka plan iş parçacığında tetiklendiğinden kullanıcı arabirimini güncelleştirmek için DispatcherQueue.TryEnqueue kullanın.