MapView Guide (WPF & WinForms)¶
Namespace: ThinkGeo.UI.Wpf / ThinkGeo.UI.WinForms
Applies to: ThinkGeo Desktop (WPF and WinForms)
Overview¶
MapView is the root control of every ThinkGeo desktop application. It is the visual surface that renders all overlays and layers, handles user interaction (pan, zoom, rotate, click), and exposes the programmatic API for controlling the map's viewport.
Every other class in the ThinkGeo desktop API connects to the map through MapView. You add LayerOverlay instances to MapView.Overlays, use the built-in TrackOverlay and EditOverlay for drawing and editing, read and set the current viewport through CenterPoint / CurrentScale / CurrentExtent, and listen to map-level events such as MapClick and CurrentExtentChanged.
Declaration¶
WinForms¶
In WinForms, MapView is a standard control created in InitializeComponent and wired to a Load event:
// In designer-generated InitializeComponent():
mapView = new ThinkGeo.UI.WinForms.MapView();
mapView.Dock = DockStyle.Fill;
mapView.MapResizeMode = MapResizeMode.PreserveScale;
mapView.MinimumScale = 200D;
mapView.MaximumScale = 1.7976931348623157E+308D;
mapView.RestrictExtent = null;
mapView.RotationAngle = 0F;
// ...
Load += Form_Load;
WPF¶
In WPF, MapView is declared in XAML with a Loaded event handler. Properties such as MapUnit, CenterPoint, CurrentScale, and overlay children can all be set directly in XAML:
<tgWpf:MapView x:Name="MapView"
Background="Black"
MinimumScale="0"
CurrentScale="50000"
CenterPoint="POINT (0 0)"
DefaultOverlaysRenderSequenceType="Concurrent"
Loaded="MapView_Loaded">
<tgWpf:MapView.Overlays>
<tgWpf:LayerOverlay TileType="SingleTile">
<tgWpf:LayerOverlay.Layers>
<tgCore:GeoImageLayer ImagePathFilename="Data/background.jpg"
CenterPoint="POINT (0 0)"
Scale="50000" />
</tgWpf:LayerOverlay.Layers>
</tgWpf:LayerOverlay>
</tgWpf:MapView.Overlays>
</tgWpf:MapView>
Async Pattern Difference¶
WPF and WinForms differ in how they call async methods from event handlers:
// WinForms — event handler is async, uses await
private async void Form_Load(object sender, EventArgs e)
{
// ... setup ...
await mapView.RefreshAsync();
}
// WPF — event handler is synchronous (RoutedEventArgs), uses fire-and-forget
private void MapView_Loaded(object sender, RoutedEventArgs e)
{
// ... setup ...
_ = MapView.RefreshAsync();
}
Initialization Order¶
The initialization order inside the load handler is important. Always follow this sequence:
- Set
MapView.MapUnit— must be set before any overlays are added. - (Optional) Wire events such as
CurrentExtentChangedandRotationAngleChanging. - Add overlays to
MapView.Overlays. - Set the initial viewport:
MapView.CenterPoint+MapView.CurrentScale, orMapView.CurrentExtent. - Call
RefreshAsync().
// WinForms canonical initialization pattern
private void Form_Load(object sender, EventArgs e)
{
// Step 1 — MapUnit first
mapView.MapUnit = GeographyUnit.Meter;
// Step 2 — wire events before first refresh so they fire on initial draw
mapView.CurrentExtentChanged += MapView_CurrentExtentChanged;
// Step 3 — add overlays
mapView.Overlays.Add(new ThinkGeoCloudVectorMapsOverlay { ... });
var layerOverlay = new LayerOverlay();
layerOverlay.TileType = TileType.SingleTile;
layerOverlay.Layers.Add("City", cityLayer);
mapView.Overlays.Add("City Overlay", layerOverlay);
// Step 4 — set initial viewport
mapView.CenterPoint = new PointShape(-10778000, 3912000);
mapView.CurrentScale = 180000;
// Step 5 — draw
_ = mapView.RefreshAsync();
}
Key Properties¶
MapUnit¶
MapView.MapUnit = GeographyUnit.Meter; // Spherical Mercator (EPSG:3857) — most common
MapView.MapUnit = GeographyUnit.DecimalDegree; // Geographic coordinates (EPSG:4326)
MapUnit tells the map what coordinate unit its overlays use. It must be set before adding overlays and must match the projection of the layers being displayed. The great majority of ThinkGeo Cloud samples use GeographyUnit.Meter because the cloud maps are served in EPSG:3857 (Spherical Mercator).
Always set
MapUnitfirst. It is the single most common source of blank or broken maps.
CurrentExtent¶
// Set — jumps the viewport to a specific bounding box immediately
MapView.CurrentExtent = new RectangleShape(-10786436, 3918518, -10769429, 3906002);
// Get — read the current visible bounding box
var bbox = MapView.CurrentExtent;
var center = bbox.GetCenterPoint();
Setting CurrentExtent directly positions the viewport without animation. It is a fast, synchronous assignment — call RefreshAsync() afterward if the map does not automatically redraw.
CenterPoint¶
// Set — re-centers the map without changing scale
MapView.CenterPoint = new PointShape(-10778000, 3912000);
// Get — current center
var center = MapView.CenterPoint;
CenterPoint and CurrentScale are the two-property equivalent of CurrentExtent. Setting both together is the most common initialization pattern.
CurrentScale¶
// Set — zooms to a specific scale denominator
MapView.CurrentScale = 180000;
// Get — read for UI display or calculations
double scale = MapView.CurrentScale;
Scale values are the denominator of a map scale ratio (e.g., 180000 means 1:180,000). Larger numbers mean a more zoomed-out view.
MapWidth / MapHeight¶
// Read-only — pixel dimensions of the rendered map surface
double widthPx = MapView.MapWidth;
double heightPx = MapView.MapHeight;
These are used exclusively with MapUtil.GetScale to compute a scale that fits a bounding box into the current control size:
// Fit a bounding box to the map control — the canonical zoom-to-extent pattern
var bbox = cityLayer.GetBoundingBox();
MapView.CenterPoint = bbox.GetCenterPoint();
MapView.CurrentScale = MapUtil.GetScale(MapView.MapUnit, bbox, MapView.MapWidth, MapView.MapHeight);
_ = MapView.RefreshAsync();
// Multiply by a factor to add padding around the edges
MapView.CurrentScale = MapUtil.GetScale(MapView.MapUnit, bbox, MapView.MapWidth, MapView.MapHeight) * 1.5;
RotationAngle¶
// Set — rotates the map around its center (in degrees; positive = clockwise)
MapView.RotationAngle = -30; // 30° counter-clockwise
// Get — current rotation
double angle = MapView.RotationAngle;
Setting RotationAngle directly changes the rotation without animation. To rotate with animation, use ZoomToAsync(center, scale, angle) instead.
MinimumScale / MaximumScale¶
// Constrain how far in or out the user can zoom
MapView.MinimumScale = 200D;
MapView.MaximumScale = 1.7976931348623157E+308D; // effectively unlimited
These properties are typically set in the designer-generated code and constrain both programmatic and interactive zoom operations.
MapResizeMode¶
MapView.MapResizeMode = MapResizeMode.PreserveScale;
// or:
MapView.MapResizeMode = MapResizeMode.PreserveScaleAndCenter;
Controls how the visible extent is recalculated when the control is resized. PreserveScale keeps the scale constant and adjusts the visible area; PreserveScaleAndCenter keeps both scale and center constant.
RestrictExtent¶
// Constrain panning so the user cannot leave a geographic region
MapView.RestrictExtent = new RectangleShape(-180, 90, 180, -90);
// Remove any panning restriction
MapView.RestrictExtent = null;
ZoomScales¶
// Replace the default zoom level set with a custom collection
MapView.ZoomScales = new Collection<double> { 500000, 200000, 100000, 50000, 10000 };
// Add a single specific zoom level
MapView.ZoomScales.Add(myCustomScale);
ZoomScales defines the discrete scale levels the map snaps to during interactive zooming and when calling ZoomInAsync / ZoomOutAsync. If not set, a default set of standard web map zoom levels is used. The ZoomToBlackHole sample builds a custom set of scales from image-layer scale properties to create a smooth animated zoom sequence.
BackgroundOverlay¶
// Set the map's background fill color
MapView.BackgroundOverlay.BackgroundBrush = new GeoSolidBrush(GeoColor.FromHtml("#42B2EE"));
BackgroundOverlay renders beneath all other overlays. Changing BackgroundBrush is how you set the map's background color — for example, to a water color for a non-Mercator world projection.
TrackOverlay / EditOverlay¶
// Built-in draw overlay
MapView.TrackOverlay.TrackMode = TrackMode.Polygon;
// Built-in edit overlay
MapView.EditOverlay.CalculateAllControlPoints();
These are singleton overlays that always exist on the map and always render above all LayerOverlay instances. See the TrackOverlay and EditOverlay guides for full documentation.
DefaultAnimationSettings¶
// Property-by-property mutation (used in most samples)
MapView.DefaultAnimationSettings.Duration = 2000; // milliseconds
MapView.DefaultAnimationSettings.Type = MapAnimationType.DrawWithAnimation;
// Or replace the entire settings object
MapView.DefaultAnimationSettings = new MapAnimationSettings
{
Type = MapAnimationType.DrawWithAnimation,
Duration = 1500,
Easing = null
};
Controls the animation that plays during ZoomToAsync transitions. Duration is in milliseconds. MapAnimationType.DrawWithAnimation gives a smooth animated zoom. Setting Duration = 0 or using a type other than DrawWithAnimation disables the animation.
Key Methods¶
RefreshAsync¶
// WinForms — redraw all overlays
await mapView.RefreshAsync();
// WPF — fire-and-forget from a synchronous handler
_ = MapView.RefreshAsync();
// Redraw a selected subset of overlays
await mapView.RefreshAsync(new Overlay[] { mapView.TrackOverlay, mapView.EditOverlay, layerOverlay });
// Redraw a single overlay (by passing it directly)
_ = MapView.RefreshAsync(_layerOverlay);
RefreshAsync() triggers a full redraw of all overlays. It returns a Task so it can be awaited in WinForms async handlers. In WPF synchronous event handlers (which have RoutedEventArgs and cannot be async), the convention throughout HowDoI is to discard the task with _ =.
Call RefreshAsync() on a specific LayerOverlay directly when only one overlay's data has changed — this is more efficient than redrawing the entire map.
ZoomInAsync / ZoomOutAsync¶
// Zoom in or out one step in the ZoomScales set
_ = mapView.ZoomInAsync();
_ = mapView.ZoomOutAsync();
These move through ZoomScales one step at a time, the same as the user scrolling the mouse wheel.
ZoomToAsync¶
ZoomToAsync has several overloads:
// Zoom to a specific scale denominator (keeps current center)
await mapView.ZoomToAsync(10000);
// Zoom to a scale that constrains to a minimum (e.g., don't zoom in closer than ZoomLevel18)
var standardZoomLevelSet = new ZoomLevelSet();
if (mapView.CurrentScale < standardZoomLevelSet.ZoomLevel18.Scale)
await mapView.ZoomToAsync(standardZoomLevelSet.ZoomLevel18.Scale);
// Zoom + pan + rotate atomically (with animation if DefaultAnimationSettings is configured)
_ = mapView.ZoomToAsync(centerPoint, scale, rotationAngle);
// Same as above, with a CancellationToken to cancel mid-animation
_ = mapView.ZoomToAsync(centerPoint, scale, rotationAngle, cancellationToken);
The three-argument and four-argument overloads are the most powerful — they move the center, set the scale, and set the rotation angle all in a single animated operation. The ZoomToBlackHole and NavigationMap samples use these extensively.
// Rotate map to north-up (0°) while keeping center and scale
_ = mapView.ZoomToAsync(mapView.CenterPoint, mapView.CurrentScale, 0);
// Jump back to a saved extent
_ = mapView.ZoomToAsync(savedCenterPoint, savedScale, savedRotationAngle, _cancellationTokenSource.Token);
CenterAtAsync¶
// Pan to a world coordinate without changing scale or rotation
var pointInMercator = ProjectionConverter.Convert(4326, 3857, new PointShape(-96.82, 33.15));
_ = mapView.CenterAtAsync(pointInMercator);
CenterAtAsync is the async equivalent of setting CenterPoint — it pans the map but leaves the scale unchanged. Use it when you only need to re-center, not zoom.
GetSnappedZoomLevelIndex¶
// Returns the index in ZoomScales of the closest level to the current scale
int zoomLevel = mapView.GetSnappedZoomLevelIndex(mapView.CurrentScale);
Useful for displaying a "zoom level" indicator in the UI. The NavigationMap and ZoomToExtents samples use this inside CurrentExtentChanged to update a status label.
FindFeatureLayer¶
// Search all overlays for a FeatureLayer with this key name
var cityLayer = (ShapeFileFeatureLayer)MapView.FindFeatureLayer("Frisco Zoning");
Searches every overlay and returns the first FeatureLayer whose key matches the argument. Useful in event handlers and helper methods that don't hold a direct reference to the overlay.
Dispose (WPF)¶
WPF windows and user controls that host MapView should implement IDisposable and call MapView.Dispose():
public partial class MyMapView : IDisposable
{
public void Dispose()
{
MapView.Dispose();
GC.SuppressFinalize(this);
}
}
In WinForms, MapView disposal is handled automatically by the form's Dispose mechanism when the control is removed from the visual tree.
Events¶
CurrentExtentChanged¶
mapView.CurrentExtentChanged += MapView_CurrentExtentChanged;
private void MapView_CurrentExtentChanged(object sender, CurrentExtentChangedMapViewEventArgs e)
{
// Read current state from the MapView directly — the event args carry no data
var center = mapView.CurrentExtent.GetCenterPoint();
var centerInDD = ProjectionConverter.Convert(3857, 4326, center);
int zoomLevel = mapView.GetSnappedZoomLevelIndex(mapView.CurrentScale);
double scale = mapView.CurrentScale;
centerPointLabel.Text = $"Center: ({centerInDD.Y:N4}, {centerInDD.X:N4})";
statusLabel.Text = $"Zoom: {zoomLevel} Scale: {scale:N0}";
}
Fires after every pan, zoom, or rotate operation that changes the visible extent. The event args do not carry the new extent — read MapView.CurrentExtent and MapView.CurrentScale directly inside the handler.
This is the canonical place to update a status bar, coordinate display, or zoom level indicator.
CurrentScaleChanged¶
mapView.CurrentScaleChanged += MapView_CurrentScaleChanged;
private void MapView_CurrentScaleChanged(object sender, CurrentScaleChangedMapViewEventArgs e)
{
scaleLabel.Text = $"Scale: {mapView.CurrentScale:N2}";
// Can also drive overlay opacity changes based on scale
foreach (var overlay in mapView.Overlays)
{
if (overlay is LayerOverlay layerOverlay)
layerOverlay.Opacity = ComputeOpacityForScale(layerOverlay, mapView.CurrentScale);
}
}
Fires specifically when the zoom scale changes. The ZoomToBlackHole sample uses this to fade image overlays in and out as the user zooms through different scale ranges.
MapClick¶
// Subscribe
mapView.MapClick += MapView_MapClick;
// Unsubscribe when the mode changes (important — avoids stale handlers)
mapView.MapClick -= MapView_MapClick;
private async void MapView_MapClick(object sender, MapClickMapViewEventArgs e)
{
// e.WorldLocation — click position as a PointShape in map coordinates
// e.WorldX, e.WorldY — same position as individual doubles
// e.MouseButton — MapMouseButton.Left, .Right, .Middle
if (e.MouseButton == MapMouseButton.Left)
{
// Use click coordinates directly for coordinate display
txtCoordinates.Text = $"{e.WorldY:0.000000},{e.WorldX:0.000000}";
}
}
Common use patterns:
Re-enabling TrackMode after a shape is drawn:
private void mapView_MapClick(object sender, MapClickMapViewEventArgs e)
{
if (mapView.TrackOverlay.TrackMode != TrackMode.Polygon)
mapView.TrackOverlay.TrackMode = TrackMode.Polygon;
}
Querying and deleting a feature at the click point:
private void MapView_MapClick(object sender, MapClickMapViewEventArgs e)
{
if (!deleteMode) return;
var featureLayer = (InMemoryFeatureLayer)_layerOverlay.Layers["featureLayer"];
// Find the nearest feature within 100 metres of the click
var nearest = featureLayer.QueryTools.GetFeaturesNearestTo(
e.WorldLocation, GeographyUnit.Meter, 1,
new Collection<string>(), 100, DistanceUnit.Meter);
if (nearest.Count > 0)
{
featureLayer.InternalFeatures.Remove(nearest[0]);
_ = MapView.RefreshAsync(_layerOverlay);
}
}
RotationAngleChanging¶
mapView.RotationAngleChanging += MapView_RotationAngleChanging;
private void MapView_RotationAngleChanging(object sender, RotationAngleChangingMapViewEventArgs e)
{
// e.NewRotationAngle — the rotation the map is transitioning to
double newAngle = e.NewRotationAngle;
// Throttle UI updates using a change threshold
if (Math.Abs(newAngle - _lastRotationAngle) > 0.1)
{
_lastRotationAngle = newAngle;
UpdateCompassRotation((float)newAngle);
}
}
Fires continuously as the user drags to rotate the map or as an animation progresses. Use the change threshold pattern shown above to avoid unnecessary UI updates during rapid rotation.
Viewport Patterns¶
Setting Viewport from a Layer's Bounding Box¶
The most common way to set the initial or result viewport is to open a layer, read its bounding box, and compute the right scale for the control size:
// Open the layer to read its extent
cityLayer.Open();
var bbox = cityLayer.GetBoundingBox();
cityLayer.Close();
// Fit the bounding box to the map control
MapView.CenterPoint = bbox.GetCenterPoint();
MapView.CurrentScale = MapUtil.GetScale(MapView.MapUnit, bbox, MapView.MapWidth, MapView.MapHeight);
// Multiply to add 50% padding around the edges
MapView.CurrentScale = MapUtil.GetScale(MapView.MapUnit, bbox, MapView.MapWidth, MapView.MapHeight) * 1.5;
_ = MapView.RefreshAsync();
Setting Viewport from an Overlay's Bounding Box¶
After running a validation or query and adding results to an overlay, zoom to fit all the result data:
var featureOverlay = (LayerOverlay)mapView.Overlays["Features Overlay"];
var overlayBBox = featureOverlay.GetBoundingBox();
mapView.CenterPoint = overlayBBox.GetCenterPoint();
mapView.CurrentScale = MapUtil.GetScale(
mapView.MapUnit, overlayBBox, mapView.MapWidth, mapView.MapHeight) * 1.5;
await mapView.RefreshAsync();
Setting Viewport Directly (No Layer Required)¶
For known coordinates — for example, a hard-coded default extent on startup:
// By bounding box
MapView.CurrentExtent = new RectangleShape(-10786436, 3918518, -10769429, 3906002);
// By center + scale
MapView.CenterPoint = new PointShape(-10778000, 3912000);
MapView.CurrentScale = 180000;
Constraining to a Minimum Scale After a Query Result¶
After zooming to query results, you may want to prevent the map from zooming in too close on a single-point result:
MapView.CurrentExtent = resultFeatureLayer.GetBoundingBox();
var standardZoomLevelSet = new ZoomLevelSet();
if (MapView.CurrentScale < standardZoomLevelSet.ZoomLevel18.Scale)
await MapView.ZoomToAsync(standardZoomLevelSet.ZoomLevel18.Scale);
await MapView.RefreshAsync();
Platform-Specific Notes¶
WPF¶
MapViewin WPF is declared in XAML withx:Name="MapView".- The load event is
Loaded="MapView_Loaded"and the handler signature isvoid MapView_Loaded(object sender, RoutedEventArgs e). - Because
RoutedEventArgshandlers cannot beasync, async methods are called with_ = someTask(fire-and-forget). - The
DefaultOverlaysRenderSequenceType="Concurrent"XAML attribute enables parallel overlay rendering, which is useful when multiple overlays can render independently. - WPF classes that host
MapViewshould implementIDisposableand callMapView.Dispose().
WinForms¶
MapViewis declared inInitializeComponent()asnew ThinkGeo.UI.WinForms.MapView().- The load event is
Load += Form_Load(or the designer-generated equivalent). - WinForms handlers can be
async void, soawait mapView.RefreshAsync()is used throughout. - Designer-generated code sets
MapResizeMode,MinimumScale,MaximumScale,RestrictExtent, andRotationAngle. MapViewdisposal is handled automatically by the WinForms control lifecycle.
Common Pitfalls¶
1. Not Setting MapUnit Before Adding Overlays¶
MapUnit must be the first line of your initialization code. Adding overlays before setting MapUnit will produce incorrect rendering or a blank map. Every HowDoI sample sets MapUnit as its very first action.
2. Reading MapWidth / MapHeight Before the Control Is Rendered¶
MapView.MapWidth and MapView.MapHeight return the pixel dimensions of the rendered control surface. If you read them before the control has been laid out (e.g., before the Load event fires), they will be zero. Always compute scales inside or after the Load / Loaded event.
3. Using CurrentExtent Instead of CenterPoint + CurrentScale¶
CurrentExtent and CenterPoint + CurrentScale are equivalent descriptions of the same viewport, but they interact subtly with MapResizeMode. Setting CenterPoint and CurrentScale separately is more predictable and is the pattern used in most HowDoI samples.
4. Not Cancelling ZoomToAsync Before Starting a New One¶
If you call ZoomToAsync(center, scale, angle, cancellationToken) while a previous animation is still running, both animations will conflict. The ZoomToBlackHole sample demonstrates the correct pattern — cancel the previous CancellationTokenSource before issuing a new ZoomToAsync call:
private void StopCurrentAnimation()
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
}
private void SomeButton_Click(object sender, EventArgs e)
{
StopCurrentAnimation();
_ = mapView.ZoomToAsync(targetPoint, targetScale, 0, _cancellationTokenSource.Token);
}
5. Forgetting to Unsubscribe MapClick¶
MapClick handlers should be unsubscribed when they are no longer needed. In the EditFeatures sample, the delete-mode handler is explicitly removed when switching away from delete mode:
mapView.MapClick -= mapView_MapClick;
Failing to unsubscribe means the handler keeps firing in the wrong modes.
Reference Table¶
Properties¶
| Property | Type | Description |
|---|---|---|
MapUnit | GeographyUnit | The coordinate unit of all overlays. Must be set first. |
CurrentExtent | RectangleShape | The visible bounding box. Get or set. |
CenterPoint | PointShape | The map center. Get or set. |
CurrentScale | double | The current scale denominator. Get or set. |
MapWidth | double | Pixel width of the rendered control surface. |
MapHeight | double | Pixel height of the rendered control surface. |
RotationAngle | double | Current map rotation in degrees. Get or set. |
MinimumScale | double | Minimum allowed zoom scale. |
MaximumScale | double | Maximum allowed zoom scale. |
MapResizeMode | MapResizeMode | How the extent adapts when the control is resized. |
RestrictExtent | RectangleShape | Constrains panning. Null removes restriction. |
ZoomScales | Collection<double> | The discrete scale levels for interactive zoom snapping. |
BackgroundOverlay | BackgroundOverlay | The map's background fill, rendered below all other overlays. |
TrackOverlay | TrackInteractiveOverlay | Built-in draw overlay, always on top. |
EditOverlay | EditInteractiveOverlay | Built-in edit overlay, always on top. |
Overlays | GeoCollection<Overlay> | The ordered collection of all overlays on the map. |
DefaultAnimationSettings | MapAnimationSettings | Animation settings for ZoomToAsync. |
Methods¶
| Method | Description |
|---|---|
RefreshAsync() | Redraw all overlays. |
RefreshAsync(Overlay[]) | Redraw a specific set of overlays. |
ZoomInAsync() | Zoom in one step in ZoomScales. |
ZoomOutAsync() | Zoom out one step in ZoomScales. |
ZoomToAsync(double scale) | Zoom to a specific scale, keeping current center. |
ZoomToAsync(PointShape, double, double) | Zoom + pan + rotate atomically with animation. |
ZoomToAsync(PointShape, double, double, CancellationToken) | Same, cancellable. |
CenterAtAsync(PointShape) | Pan to a point without changing scale. |
GetSnappedZoomLevelIndex(double) | Returns the nearest zoom level index for a given scale. |
FindFeatureLayer(string) | Search all overlays for a FeatureLayer by key name. |
Dispose() | Releases unmanaged resources (WPF — call from IDisposable). |
Events¶
| Event | Args Type | Description |
|---|---|---|
CurrentExtentChanged | CurrentExtentChangedMapViewEventArgs | Fires after every pan, zoom, or rotate. Read MapView properties for current state. |
CurrentScaleChanged | CurrentScaleChangedMapViewEventArgs | Fires when zoom level changes. |
MapClick | MapClickMapViewEventArgs | Mouse click on the map. e.WorldLocation (PointShape), e.WorldX, e.WorldY, e.MouseButton. |
RotationAngleChanging | RotationAngleChangingMapViewEventArgs | Fires during rotation. e.NewRotationAngle is the target angle. |