Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
SDK per app di Windows e WinUI 3 forniscono API e controlli per la visualizzazione delle mappe, il rilevamento della posizione dell'utente e la configurazione dei recinti virtuali. Usare queste funzionalità per creare app che mostrano mappe interattive con puntini, tenere traccia della posizione dell'utente e attivare azioni quando l'utente entra o lascia un'area geografica.
Questo articolo presenta ogni funzionalità e include un esempio completo che combina MapControl, Geolocatore GeofenceMonitor in una singola app funzionante.
Visualizza le mappe con MapControl
MapControl visualizza una mappa interattiva basata su Mappe di Azure. È possibile aggiungere puntini, livelli e rispondere alle interazioni dell'utente, ad esempio panoramica, zoom e clic.
MapControl richiede un account Mappe di Azure. Vedere Gestire l'account Mappe di Azure per creare un account e ottenere un token di servizio.
Per istruzioni dettagliate sull'utilizzo, vedere MapControl.
<MapControl x:Name="myMap"
MapServiceToken="YOUR_AZURE_MAPS_TOKEN"
Height="400" />
Note
Le API UWP MapControl e Windows.Services.Maps sono deprecate e potrebbero non essere disponibili nelle versioni future di Windows. Le app WinUI 3 devono usare il nuovo MapControl descritto in precedenza. Per altre informazioni, vedere Risorse per le funzionalità deprecate.
Rilevare la posizione dell'utente
Windows. Le API Devices.Geolocation consentono di ottenere la posizione geografica del dispositivo. Queste API funzionano sia nelle app UWP che nelle app SDK per app di Windows (WinUI 3). È possibile:
- Ottenere una posizione una tantum usando Geolocator.GetGeopositionAsync.
- Tenere traccia delle modifiche di posizione nel tempo usando l'evento Geolocator.PositionChanged .
- Monitora le modifiche dello stato delle visite con GeovisitMonitor per il rilevamento della posizione a basso consumo energetico.
Per una guida dettagliata, vedere Ottenere la posizione dell'utente.
Configura geofence
Un geofence definisce un confine geografico. L'app riceve notifiche quando l'utente entra o esce dal limite. I geofence sono utili per promemoria, avvisi o distribuzione di contenuti in base alla posizione.
Per istruzioni sulla creazione e il monitoraggio dei recinti virtuali, vedere Configurare un recinto virtuale.
Funzionalità di localizzazione e privacy
Tutte le API di posizione richiedono la funzionalità Location dichiarata nel manifesto del pacchetto dell'app. È anche necessario chiamare Geolocator.RequestAccessAsync in fase di esecuzione prima di accedere ai dati della posizione.
Windows offre agli utenti il controllo sulle app che possono accedere alla loro posizione tramite Impostazioni > Privacy e posizione di sicurezza>. L'app deve gestire il caso in cui l'utente nega o revoca l'accesso alla posizione.
Esempio completo
L'esempio seguente riunisce MapControl, Geolocatore GeofenceMonitor in una singola finestra di WinUI 3. Se non è configurata alcuna chiave Mappe di Azure, la mappa si degrada normalmente mentre la georilevazione e il recinto virtuale continuano a funzionare.
Prerequisiti
- SDK per app di Windows 2.2 o versione successiva
- Chiave Mappe di Azure necessaria per visualizzare i riquadri della mappa. Senza una chiave valida, MapControl esegue il rendering ma mostra una mappa vuota.
- La funzionalità del dispositivo Location dichiarata in
Package.appxmanifest:
<DeviceCapability Name="location" />
Impostare la chiave Mappe di Azure come variabile di ambiente prima di eseguire l'app:
$env:AZURE_MAPS_KEY = "your-key-here"
MainWindow.xaml
Un pannello di controllo largo 300 pixel sulla sinistra, con pulsanti e testo di stato, e un MapControl sulla destra. Viene visualizzata una sovrimpressione quando manca il tasto Mappe di Azure.
<?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}");
}
Modelli chiave
-
MapControlè integrato in SDK per app di Windows 1.6 e versioni successive. ImpostareMapServiceTokensul tasto Mappe di Azure. -
TryConfigureMapcontrolla la variabile di ambiente all'avvioAZURE_MAPS_KEY. Se la variabile è vuota, la mappa si chiude e un overlay spiega come risolvere il problema — senza arresti anomali né mappe vuote. -
DeviceCapability Name="location"inPackage.appxmanifestè obbligatorio oGeolocator.RequestAccessAsyncrestituisceDenied. -
GeofenceMonitor.GeofenceStateChangedviene attivato su un thread in background, quindi usareDispatcherQueue.TryEnqueueper aggiornare l'interfaccia utente.