Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
A Geofence defines a circular geographic boundary around a point of interest. Your app receives notifications when the user enters or exits the boundary. Geofences are useful for location-based reminders, alerts, check-ins, and contextual content delivery.
This article shows how to create a geofence, monitor state changes, and handle geofence events in a Windows App SDK (WinUI 3) app.
Prerequisites
- A WinUI 3 project created from the Blank App, Packaged (WinUI 3 in Desktop) template.
- The Location capability declared in the package manifest. See Get the user's location for instructions.
Request location access
Call Geolocator.RequestAccessAsync before creating or monitoring geofences.
using Windows.Devices.Geolocation;
using Windows.Devices.Geolocation.Geofencing;
var accessStatus = await Geolocator.RequestAccessAsync();
if (accessStatus != GeolocationAccessStatus.Allowed)
{
StatusText.Text = "Location access is required for geofencing.";
return;
}
Create a geofence
Define a geofence by specifying an identifier, a geographic center, a radius in meters, and which state transitions to monitor (entered, exited, or removed).
var position = new BasicGeoposition
{
Latitude = 47.6062,
Longitude = -122.3321
};
var geocircle = new Geocircle(position, 200); // 200-meter radius
var geofence = new Geofence(
"SeattleDowntown", // Unique identifier
geocircle, // Geographic boundary
MonitoredGeofenceStates.Entered | // States to monitor
MonitoredGeofenceStates.Exited,
false, // Single use: false = persistent
TimeSpan.FromSeconds(10) // Dwell time before triggering
);
GeofenceMonitor.Current.Geofences.Add(geofence);
Geofence parameters
| Parameter | Description |
|---|---|
id |
A unique string that identifies the geofence. Use this to distinguish events from different geofences. |
geoshape |
A Geocircle that defines the boundary. Only circular boundaries are supported. |
monitoredStates |
Which transitions to monitor: Entered, Exited, or Removed. Combine with the | operator. |
singleUse |
If true, the geofence triggers once and is removed automatically. |
dwellTime |
How long the user must remain inside (or outside) the boundary before the event fires. Helps filter out brief crossings. |
Monitor geofence events in the foreground
Subscribe to the GeofenceMonitor.Current.GeofenceStateChanged event to receive notifications while your app is running.
GeofenceMonitor.Current.GeofenceStateChanged += OnGeofenceStateChanged;
Read the reports and update the UI. The event fires on a background thread, so use DispatcherQueue to marshal UI updates.
private void OnGeofenceStateChanged(GeofenceMonitor sender, object args)
{
var reports = sender.ReadReports();
DispatcherQueue.TryEnqueue(() =>
{
foreach (var report in reports)
{
var state = report.NewState;
var id = report.Geofence.Id;
switch (state)
{
case GeofenceState.Entered:
StatusText.Text = $"Entered geofence: {id}";
break;
case GeofenceState.Exited:
StatusText.Text = $"Exited geofence: {id}";
break;
case GeofenceState.Removed:
StatusText.Text = $"Geofence removed: {id}";
// Re-add the geofence if it was removed due to expiration
break;
}
}
});
}
Monitor geofence status changes
Use GeofenceMonitor.Current.StatusChanged to detect when geofence monitoring is disabled — for example, when the user turns off location services.
GeofenceMonitor.Current.StatusChanged += (sender, args) =>
{
DispatcherQueue.TryEnqueue(() =>
{
var status = sender.Status;
if (status == GeofenceMonitorStatus.Disabled)
{
StatusText.Text = "Geofence monitoring is disabled. Check location settings.";
}
});
};
Tip
When using geofences, monitor permission changes through GeofenceMonitor.StatusChanged rather than Geolocator.StatusChanged. A GeofenceMonitorStatus value of Disabled is equivalent to a PositionStatus of Disabled, but GeofenceMonitorStatus provides more context for geofencing scenarios.
Remove a geofence
Remove a geofence by finding it in the GeofenceMonitor.Current.Geofences collection.
var geofences = GeofenceMonitor.Current.Geofences;
var target = geofences.FirstOrDefault(g => g.Id == "SeattleDowntown");
if (target != null)
{
geofences.Remove(target);
}
Best practices
- Set a reasonable dwell time. A dwell time of at least 10 seconds helps filter out GPS jitter and prevents false triggers at boundary edges.
- Use a radius of at least 50 meters. GPS accuracy varies by device and environment. A radius smaller than 50 meters may produce unreliable results.
- Check internet access if needed. If your app performs network operations when a geofence event fires (such as sending a notification to a server), verify connectivity before creating the geofence.
- Handle the
Removedstate. Geofences can be removed by the system if they expire or if the system is under resource pressure. Check forGeofenceState.Removedand re-create the geofence if your scenario requires it. - Don't monitor foreground and background simultaneously for the same geofence unless necessary. If you do, unregister the foreground listener when the app is suspended and re-register when it resumes.
Related articles
Windows developer