Creating and working with basemap layers



About creating and working with basemap layers

A basemap layer is a user-defined group of layers that are drawn continuously during navigation. BasemapLayer implements IGroupLayer and in many ways it behaves in the same way as GroupLayer. BasemapLayer draws with a high-performance multi-threaded drawing engine that can significantly improve the display speed and responsiveness of your map. ArcMap is the primary consumer of BasemapLayer; however, the MapControl and ArcReader also have the same performance benefits when working with BasemapLayer.
Components using the output pipeline of the ArcGIS two-dimensional (2D) drawing engine, such as ArcGIS for Server and the three-dimensional (3D) applications drawing draped content, will not see a benefit from using BasemapLayer. Optimized map services in ArcGIS for Server use the same drawing engine as BasemapLayer and should be used to achieve fast map services.

Unlike ArcMap’s primary drawing engine, the BasemapLayer drawing engine is not interrupted by interaction with the map or application menus. This means that you can continue to work within the ArcMap menus and Contents window or continue to navigate through the map while BasemapLayer draws. This behavior comes with some limitations, in that most layer properties are hidden from editing when a layer is in a basemap layer. This is done to prevent changes to layer properties that would in turn cause the display cache to need to be invalidated. In the ArcMap user interface (UI), layer property pages are hidden from the user to block these types of updates. At the application programming interface (API) level, this hiding is done by wrapping the real layer with a basemap sublayer.
BasemapSubLayer selectively exposes layer behavior for common tasks, such as identify. Properties that are changed on the BasemapSubLayer implemented interfaces are handled by BasemapSubLayer and the basemap cache is invalidated if necessary. If you access the inner layer via IBasemapSubLayer.Layer, you need to manage the updates by notifying BasemapLayer that a sublayer has changed. 
There are some data sources, layer types, and symbology properties that are not compatible with the basemap layer's drawing engine. When programmatically adding layers to a BasemapLayer, use IBasemapSubLayer.GetConversionStatus to confirm the success or failure of the operation. 
RasterBasemapLayer is a special type of BasemapLayer that wraps a single raster layer for high performance display in image analysis scenarios.
The caching mechanism behind BasemapLayer uses a combination of in-memory and disk caches. Limit your map to as few basemap layers as possible to limit memory consumption. In most circumstances, it is not practical to have more than five in a map.
The following code example shows how to create a basemap layer, add a layer to it, and add it to a map:
[C#]
private void CreateBasemapLayerAndAddLayerToIt(IMap map, ILayer layer)
{
    IBasemapLayer basemapLayer = new BasemapLayerClass();
    IGroupLayer basemapGroupLayer = basemapLayer as IGroupLayer;
    basemapGroupLayer.Add(layer);
    basemapGroupLayer.Name = "Basemap Content";
    map.AddLayer((ILayer)basemapLayer);
}
[VB.NET]
Private Sub CreateBasemapLayerAndAddLayerToIt(ByVal map As IMap, ByVal layer As ILayer)
    Dim basemapLayer As IBasemapLayer = New BasemapLayerClass()
    Dim basemapGroupLayer As IGroupLayer = TryCast(basemapLayer, IGroupLayer)
    basemapGroupLayer.Add(layer)
    basemapGroupLayer.Name = "Basemap Content"
    
    map.AddLayer(DirectCast(basemapLayer, ILayer))
End Sub

Accessing a basemap sublayer

The following code example shows how to access a basemap sublayer, retrieve the inner layer, update a property on the inner layer, and notify the basemap layer of the change. The notification invalidates the layer's internal cache so that the content is redrawn to reflect the update. In this example, the update clears the definition expression of a feature layer.
[C#]
private void UpdateBasemapSublayerAndNotify(IBasemapLayer basemapLayer, IMap map)
{
    ICompositeLayer basemapCompositeLayer = basemapLayer as ICompositeLayer;
    IBasemapSubLayer basemapSubLayer = basemapCompositeLayer.get_Layer(0)as
        IBasemapSubLayer;
    ILayer innerLayer = basemapSubLayer.Layer;
    IFeatureLayer featureLayer = innerLayer as IFeatureLayer;
    if (featureLayer != null)
    {
        IFeatureLayerDefinition featureLayerDef = featureLayer as
            IFeatureLayerDefinition;
        featureLayerDef.DefinitionExpression = "";
    }
    //When performing operations against the wrapped layer that change properties, you must 
    //notify the basemaplayer so the display cache can be recreated if necessary.
    basemapLayer.NotifyLayerChanged(basemapSubLayer as ILayer,
        esriLayerEventHint.esriLayerEventHintProperties, null);
    IActiveView activeView = map as IActiveView;
    activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, basemapLayer as
        object, null);
}
[VB.NET]
Private Sub UpdateBasemapSublayerAndNotify(ByVal basemapLayer As IBasemapLayer, ByVal map As IMap)
    Dim basemapCompositeLayer As ICompositeLayer = TryCast(basemapLayer, ICompositeLayer)
    Dim basemapSubLayer As IBasemapSubLayer = TryCast(basemapCompositeLayer.get_Layer(0), IBasemapSubLayer)
    Dim innerLayer As ILayer = basemapSubLayer.Layer
    Dim featureLayer As IFeatureLayer = TryCast(innerLayer, IFeatureLayer)
    If featureLayer IsNot Nothing Then
        Dim featureLayerDef As IFeatureLayerDefinition = TryCast(featureLayer, IFeatureLayerDefinition)
        featureLayerDef.DefinitionExpression = ""
    End If
    
    'When performing operations against the wrapped layer that change properties, you must
    'notify the basemaplayer so the display cache can be recreated if necessary.
    basemapLayer.NotifyLayerChanged(TryCast(basemapSubLayer, ILayer), esriLayerEventHint.esriLayerEventHintProperties, Nothing)
    
    Dim activeView As IActiveView = TryCast(map, IActiveView)
    
    activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, TryCast(basemapLayer, Object), Nothing)
End Sub

Creating a raster basemap layer

The following code example shows how to create a RasterBasemapLayer via the RasterBasemapLayerFactory combined with the AddLayersOperation, which allows for the undo of the operation in ArcMap. This is the preferred way to add layers to a map when working in ArcGIS for Desktop.
[C#]
private void CreateRasterBasemapLayer(IRasterLayer rasterLayer, IMap map)
{
    IRasterBasemapLayerFactory rasterBMLFactory = new RasterBasemapLayerFactoryClass
        ();
    IRasterBasemapLayer rasterBML = rasterBMLFactory.Create(rasterLayer);
    ILayer layer = (ILayer)rasterBML;
    layer.Name = layer.Name + " Accelerated";
    IAddLayersOperation addLayersOp = new AddLayersOperationClass();
    addLayersOp.SetDestinationInfo(0, map, null);
    addLayersOp.AddLayer(layer);
    addLayersOp.Name = "Add Accelerated Raster Layer";
    IOperation op = addLayersOp as IOperation;
    op.Do(); // Add the layer.
}
[VB.NET]
Private Sub CreateRasterBasemapLayer(ByVal rasterLayer As IRasterLayer, ByVal map As IMap)
    Dim rasterBMLFactory As IRasterBasemapLayerFactory = New RasterBasemapLayerFactoryClass()
    Dim rasterBML As IRasterBasemapLayer = rasterBMLFactory.Create(rasterLayer)
    Dim layer As ILayer = DirectCast(rasterBML, ILayer)
    layer.Name = layer.Name & " Accelerated"
    
    Dim addLayersOp As IAddLayersOperation = New AddLayersOperationClass()
    addLayersOp.SetDestinationInfo(0, map, Nothing)
    addLayersOp.AddLayer(layer)
    addLayersOp.Name = "Add Accelerated Raster Layer"
    Dim op As IOperation = TryCast(addLayersOp, IOperation)
    ' Add the layer.
    op.Do()
End Sub

Basemap layer shaders

The basemap layer offers two mechanisms—IShader and IAdvancedShader—to modify the red, green, blue (RGB) values displayed on the screen. By specifying a function that processes the RGB values, you can manipulate the display of a basemap layer. These shaders process the display of the basemap layer through a pre-computed lookup table, and changes to the shaders do not invalidate the cache. Because of this, you can define multiple shaders and combine or reorder them with little to no hit to the performance.
The difference between the two shaders is that IAdvancedShader allows you to recalculate the lookup table based on the input of an image. This is used, for example, to implement the Dynamic Range Adjustment (DRA) option in accelerated raster layers.
The shaders are for visualization only, so be aware that the shader's effects will not be visible in output (for example, if you print or export the map).

Basemap layer dimming

When using the basemap layer to display a cartographically complex basemap, it can be helpful to "mute" or "dim" the basemap layer to allow the user to see their operational data more clearly. 
Use the ILayerEffectDIM interface to change this setting on the basemap layer. Like other layer effects, the results of dimming will be visible on output.

Basemap layer display settings

The basemap layer has some display-level options that can be changed for hardware acceleration and for the behavior of basemap layers over remote desktop. These properties can be investigated and modified using the IGlobalScreenDisplaySettings interface.
The IGlobalScreenDisplaySettings.CanEnableHardwareAcceleration method can be used to determine whether the system on which your application is running is capable of hardware acceleration. This can be useful if you need to decide whether to provide this option in your application's UI.
Setting IGlobalScreenDisplaysettings.EnableHardwareAcceleration to true attempts to enable hardware acceleration on this display. If it is not possible to use hardware acceleration, it will be disabled regardless of the state of this property.
Lastly, you might want to disable the basemap layer's continuous display when your user is connected via a remote desktop session. To do so, change IGlobalScreenDisplaySettings.EnableContinuousUpdatesOverRemoteDesktop to false. This  causes basemap layers to refresh like layers that are not in basemap layers when the user is connected via remote desktop. 






To use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
Development licensing Deployment licensing
ArcGIS for Desktop Basic ArcGIS for Desktop Basic
ArcGIS for Desktop Standard ArcGIS for Desktop Standard
ArcGIS for Desktop Advanced ArcGIS for Desktop Advanced
Engine Developer Kit Engine