Waiting for Map initialization

When an operation view is opened, all widgets contained in the view are deserialized. When all the persisted properties have been deserialized (those marked with the DataMember attribute), the IWidget.Activate method is called on each widget.

When a MapWidget is deserialized, its Map property is set by retrieving the webmap stored in ArcGIS Online or Portal for ArcGIS, which is an asynchronous operation. The application does not await the completion of this call before progressing to activate other widgets. For this reason, the Map property of a MapWidget may be null (Nothing in Visual Basic) even after the MapWidget has been activated; the Map will become set at some point in the future, unless there is a problem retrieving the webmap in which case it may remain null.

It is recommended therefore that the Map property is checked before use, especially in code that could run immediately after opening an operation view, for example the constructor, or Activate methods.

How to wait until the Map is initialized

The Initialized event on the MapWidget class occurs when the Map of a MapWidget becomes initialized after an operation view is opened. This event can therefore be used to wait upon the Map property being set, if it is found to be null.

The code below demonstrates a widget that finds a specific map widget in the Activate method; if the Map of the MapWidget is null, then an event handler is added for the Initialized event, in which a reference to the Map is set. This Map can then be accessed for properties such as Extent or Layers.

Handling MapWidget.Initialized event

private client.Map _map = null;

[DataMember(Name = "mapWidgetId")]
public string MapWidgetId { get; set; }

public void Activate()
{
  if (!string.IsNullOrEmpty(MapWidgetId))
  {
    MapWidget mapW = OperationsDashboard.Instance.Widgets.Where(w => w.Id == MapWidgetId).FirstOrDefault() as MapWidget;
    if (mapW != null)
    {
      if (mapW.IsInitialized)
      {
        _map = mapW.Map;
      }
      else
      {
        mapW.Initialized += (s, e) =>
        {
          _map = mapW.Map;
        };
      }
    }
  }
}

Handling MapWidget.Initialized event

Private Property _map As client.Map = Nothing

 <DataMember(Name:="mapWidgetId")>
 Public Property MapWidgetId As String

 Public Sub Activate() Implements IWidget.Activate

  If (Not String.IsNullOrEmpty(MapWidgetId)) Then
    Dim mapW As MapWidget = OperationsDashboard.Instance.Widgets.Where(Function(w) w.Id = MapWidgetId).FirstOrDefault()
    If (Not mapW Is Nothing) Then
      If (mapW.IsInitialized) Then
        _map = mapW.Map
      End If
    Else
      AddHandler mapW.Initialized, Sub(s, e)
                                     _map = mapW.Map
                                   End Sub
    End If
  End If
End Sub
NoteNote:

It is possible that some layers within the map are still not initialized at the point when the map is initialized, if those layers reference services which are particularly slow to respond, or cannot be reached at all.

Refer to the topics under ArcGIS Runtime SDK for WPF > Working with the map for more information about dealing with the ESRI.ArcGIS.Client.Map.

1/27/2015