Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Windows App SDK och WinUI 3 tillhandahåller API:er och kontroller för att visa kartor, identifiera användarens plats och konfigurera geofences. Använd de här funktionerna för att skapa appar som visar interaktiva kartor med stift, spårar användarens position och utlöser åtgärder när användaren går in i eller lämnar ett geografiskt område.
Den här artikeln introducerar varje funktion och innehåller ett komplett exempel som kombinerar MapControl, Geolocatoroch GeofenceMonitor i en enda fungerande app.
Visa kartor med MapControl
MapControl visar en interaktiv karta som drivs av Azure Maps. Du kan lägga till stift, lager och svara på användarinteraktioner som panorering, zooma och klicka.
MapControl kräver ett Azure Maps konto. Se Hantera ditt Azure Maps-konto för att skapa ett konto och hämta en tjänsttoken.
Detaljerade användningsinstruktioner finns i MapControl.
<MapControl x:Name="myMap"
MapServiceToken="YOUR_AZURE_MAPS_TOKEN"
Height="400" />
Note
UWP MapControl och Windows. Services.Maps-API:er är inaktuella och kanske inte är tillgängliga i framtida versioner av Windows. WinUI 3-appar bör använda den nya MapControl som beskrivs ovan. Mer information finns i Resurser för inaktuella funktioner.
Identifiera användarens plats
Windows.Devices.Geolocation-API:erna gör att du kan hämta enhetens geografiska position. Dessa API:er fungerar i både UWP- och Windows App SDK-appar (WinUI 3). Du kan:
- Skaffa en engångsposition med geolocator.GetGeopositionAsync.
- Spåra positionsändringar över tid med hjälp av händelsen Geolocator.PositionChanged .
- Övervaka besökstillståndsändringar med geovisitMonitor för batterieffektiv platsmedvetenhet.
En stegvis guide finns i Hämta användarens plats.
Konfigurera geofences
En geofence definierar en geografisk gräns. Appen får meddelanden när användaren går in i eller avslutar gränsen. Geofences är användbara för platsbaserade påminnelser, aviseringar eller innehållsleverans.
Anvisningar om hur du skapar och övervakar geofences finns i Konfigurera en geofence.
Platskapacitet och sekretess
Alla plats-API:er kräver den platsfunktion som deklareras i appens paketmanifest. Du måste också anropa Geolocator.RequestAccessAsync under körning innan du får åtkomst till platsdata.
Windows ger användarna kontroll över vilka appar som kan komma åt deras plats via Inställningar > Sekretess och säkerhetsplats>. Din app ska hantera det fall där användaren nekar eller återkallar platsåtkomst.
Fullständigt exempel
I följande exempel sammanförs MapControl, Geolocatoroch GeofenceMonitor i ett enda WinUI 3-fönster. Om ingen Azure Maps-nyckel har konfigurerats fungerar kartan fortfarande, men med begränsad funktionalitet, medan geolokalisering och geofencing fortsätter att fungera.
Förutsättningar
- Windows App SDK 2.2 eller senare
- En Azure Maps nyckel – krävs för att visa kartpaneler. Utan en giltig nyckel renderas MapControl men visar en tom karta.
- Funktionen Platsenhet som deklareras i
Package.appxmanifest:
<DeviceCapability Name="location" />
Ange din Azure Maps nyckel som en miljövariabel innan du kör appen:
$env:AZURE_MAPS_KEY = "your-key-here"
MainWindow.xaml
En kontrollpanel på 300 bildpunkter till vänster med knappar och statustext och en MapControl till höger. Ett överlägg visas när Azure Maps-nyckeln saknas.
<?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="" 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}");
}
Nyckelmönster
-
MapControlär inbyggd i Windows App SDK 1.6 och senare. AngeMapServiceTokentill din Azure Maps-nyckel. -
TryConfigureMapAZURE_MAPS_KEYkontrollerar miljövariabeln vid start. Om variabeln är tom komprimeras kartan och ett överlägg förklarar hur du åtgärdar det – ingen krasch, ingen tom karta. -
DeviceCapability Name="location"iPackage.appxmanifestkrävs ellerGeolocator.RequestAccessAsyncreturnerarDenied. -
GeofenceMonitor.GeofenceStateChangedutlöses i en bakgrundstråd, så användDispatcherQueue.TryEnqueueför att uppdatera användargränssnittet.
Relaterade artiklar
Windows developer