Guidelines, best practices, tips, and tricks

In this topic

This topic provides suggestions for improving your development experience and describes some best practices when working with ArcGIS Runtime SDK for .NET.

Ensure required objects have been loaded

A common pitfall when working with asynchronous execution is the potential to refer to objects that are not yet available. When your page initializes, for example, you may have code that tries to manipulate a layer in the Map. If the layer has not been loaded, you're code is likely to encounter an exception. In an ArcGIS Runtime app, you'll often need to know things like:

Has a particular layer loaded?

Has a particular layer failed to load (and what is the exception)?

Have all layers loaded?

Is the Map ready?

Within the ArcGIS Runtime API there are events and async tasks which help determine when you can
access functionality with predictable results and/or without
exceptions. These are described in the following sections in the order in which they typically occur.

Has a particular layer loaded?

Use the MapView.LayerLoaded event to determine when a specific layer has loaded in the
map or whether any layers failed to load (LayerLoadedEventArgs has
a LoadError property which contains the exception). The following example illustrates handling this event for the map view.

Tip:

If you use the ArcGIS Runtime project or
item templates in Visual Studio, this event will be registered in XAML and contain an event
handler in the code behind.

Have all layers been loaded?

The awaitable MapView.LayersLoadedAsync task can be used to make sure all layers have loaded before proceeding with your code. The following example shows the appropriate pattern for using this method.

Is the map ready?

The Map is ready for interaction, such as zooming to an area of interest, only after its spatial reference has been established. Use the MapView.SpatialReferenceChanged event to determine when this occurs, as shown in the following example.

Asynchronous code in a constructor

Asynchronous code that runs using the await keyword must be inside a function that is marked with the async keyword in its signature. Some functions, such as the constructor for your page or window, cannot be altered to be asynchronous. To run asynchronous code from such a function, you must call out to another function. The following example illustrates calling an asynchronous helper function from a constructor to do some initialization work.

Note:

Setting the viewpoint inside the map element is not possible in
Windows Store or Windows Phone apps because those environments lack
support for the required TypeConverters.

For setting the initial extent in the code behind, it's recommended to use the base Viewpointclass, which has similar constructor overloads.

// define a viewpoint with coords that define an extent and a spatial reference
mapView.Map.InitialViewpoint = new Viewpoint(new Envelope(-117.18268, 32.69585, -117.13387, 32.71853, SpatialReferences.Wgs84));
// define a viewpoint with a center point and scale denominator (1:50,000 in this example)
mapView.Map.InitialViewpoint = new Viewpoint(new MapPoint(-117.15, 32.705, SpatialReferences.Wgs84), 50000);

Set the MapView spatial reference

The spatial reference of the map view is read-only and is determined by
the spatial reference of the map it contains. This can either be set explicitly
to force a specific spatial reference or will otherwise be taken
from the first layer with a valid SpatialReference in the
Map.Layers collection.

Note:

Setting the Map.SpatialReference property in XAML is not supported
except when binding the property to an existing
SpatialReference instance.

Specify spatial references

If you need a WGS1984 or Web Mercator Auxiliary Sphere spatial reference, you can
use the SpatialReferences static convenience class which currently
has two options: SpatialReferences.Wgs84 and SpatialReferences.WebMercator. These
options will internally use the SpatialReference.Create(int wkid) method to return a spatial reference instance.

When specifying a value other than Web Mercator or WGS 1984 for a geometry's SpatialReference property, you
should use the SpatialReference.Create method which will
ensure instance re-use.

Note:

You should avoid creating new SpatialReference instances, for example: var sr = new SpatialReference(4326);.

Create geometry

There are a couple options for creating geometry. Use the method that is best suited for your requirements and for the geometry type with which you are working.

Note:

Geometry is immutable, which means geometry instances cannot be modified once created.

Create points

For map points, you should always use the MapPoint constructor to create new instances. The constructor requires x and y coordinates, and has several overrides that allow you to also specify a spatial reference, a z coordinate, or an m coordinate.

For consistency with other geometry types, the API includes a MapPointBuilder that you can use to create a point. This provides the only way to create an empty MapPoint (undefined values for the x and y coordinates).

Create polylines and polygons

The constructors for Polyline and Polygon have several overrides that allow you to create a new geometry from a collection of points or segments. If the points or segments passed into the constructor have a spatial reference, then the new geometry will pick that up. Otherwise, you should specify a spatial reference in the constructor overload of Polygon or Polyline.

// create a polygon from a collection of vertices (MapPoints) and specify a spatial reference
var myPolygon = new Esri.ArcGISRuntime.Geometry.Polygon(mapPoints, SpatialReferences.Wgs84);
// create a polyline from a collection of segments that have a spatial reference defined (and will be used by the new polyline)
var myPolyline = new Esri.ArcGISRuntime.Geometry.Polyline(segments);

For large numbers of points, the PointCollection class provides efficient storage of coordinates and avoids the creation of many MapPoint instances. This provides an efficient way to build up a polygon or polyline from a large number of points, perhaps read from an external file or database, for example.

// create an empty point collection
var myPoints = new Esri.ArcGISRuntime.Geometry.PointCollection(SpatialReferences.WebMercator);
// set the capacity if you know the maximum number of points to add
myPoints.Capacity = maxNumberOfPoints;
// repeat adding vertex coordinates directly into the PointCollection (no MapPoint instances)
while (moPoints)
{
// ... read x/y coordinate values ...
myPoints.Add(x, y);
// ... see if there are more ...
}
// pass the point collection to the Polygon constructor
var myPolygon = new Esri.ArcGISRuntime.Geometry.Polygon(myPoints);

Note:

You can create a multipart polygon using a list of point collections (List<PointCollection>), where each PointCollection contains the vertices for a part (ring, in other words).

Update geometry

You can use the PolylineBuilder and PolygonBuilder classes to create and modify a new shape. The builder is best suited for editing workflows where the user may be adding, inserting or removing parts of a geometry interactively. Because Geometry is immutable, the builder provides a way to make changes to a working geometry. Use the ToGeometry method on PolylineBuilder or PolygonBuilder to get the polygon or polyline from the builder.

When updating or modifying existing geometries, use
PolylineBuilder and PolygonBuilderclasses to modify the geometry. The easiest way is to pass an existing
geometry to the constructor for the builder.

var polylineBuilder = new PolylineBuilder(polyline); // Create builder based on existing one
polylineBuilder.Parts[0].RemoveAt(0);
polylineBuilder.AddPoint(-117.456, 34.554); // adding a point to last part
polyline = polylineBuilder.ToGeometry(); // get updated geometry

XML namespace references

Be consistent with naming of XML namespace references in your XAML code. If you use the same names for these references in all your projects, you'll be able to copy and paste XAML between apps without having to modify the prefixes used to refer to namespaces.
The ArcGIS Runtime for .NET samples use the following namespace designations.

xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013"

Tip:

If you're consistent with names for common objects in your UI (MapView, Map, layers, and so on), it will also make it easier to copy and paste .NET code between projects.