Ejemplo n.º 1
0
        /// <summary>
        /// Initializes a <see cref="Map"/> object based on a web map
        /// </summary>
        /// <param name="map">The map to initialize</param>
        /// <param name="e">The <see cref="GetMapCompletedEventArgs"/> object containing the web map's information.
        /// This is the event args type returned to the <see cref="Document.GetMapCompleted"/> event.</param>
        public static void InitializeFromWebMap(this Map map, GetMapCompletedEventArgs e, EventHandler <EventArgs> onLayerInitFailed = null)
        {
            map.Layers.Clear();

            if (e.Map.Extent != null && e.Map.Extent.SpatialReference != null &&
                e.Map.Extent.SpatialReference.IsWebMercator() &&
                double.IsNegativeInfinity(e.Map.Extent.YMin) &&
                double.IsPositiveInfinity(e.Map.Extent.YMax))
            {
                e.Map.Extent.YMin = double.NaN;
                e.Map.Extent.YMax = double.NaN;
            }

            map.Extent = e.Map.Extent;
            List <Layer>        layers        = new List <Layer>();
            List <Layer>        basemapLayers = new List <Layer>();
            IEnumerable <Layer> allLayers     = e.Map.Layers.FlattenLayers();
            List <string>       featureCollectionLayerNames = new List <string>();

            // Create collection of layers to add to the map based on the layers in the web map
            foreach (Layer layer in allLayers)
            {
                // Set ShowLegend to true for each layer.  The framework handles layer visibility
                // in MapContents otherwise.
                layer.ShowLegend = true;

                if (layer is ESRI.ArcGIS.Client.Bing.TileLayer)
                {
                    ESRI.ArcGIS.Mapping.Core.LayerExtensions.SetUsesBingAppID((ESRI.ArcGIS.Client.Bing.TileLayer)layer, true);
                }

                layer.ProcessWebMapProperties(e.DocumentValues);

                // Check whether any layers flagged for adding to the map have the same ID as the current one.  Layers
                // with the same ID represent feature collections that show up as part of the same layer in the online
                // viewers, but are actually serialized as separate layers.
                if (!(layer is GraphicsLayer) || !layers.Any(l => l.ID == layer.ID ||
                                                             l.DisplayName == layer.DisplayName ||
                                                             featureCollectionLayerNames.Contains(layer.DisplayName)))
                {
                    if ((bool)(layer.GetValue(ESRI.ArcGIS.Client.WebMap.Document.IsBaseMapProperty)))
                    {
                        basemapLayers.Add(layer);
                    }

                    layers.Add(layer);
                }
                else // Layer belongs to a multi-layer feature collection.  Combine with layer already included in the list.
                {
                    GraphicsLayer currentLayer = layers.First(l => l.ID == layer.ID ||
                                                              l.DisplayName == layer.DisplayName ||
                                                              featureCollectionLayerNames.Contains(layer.DisplayName)) as GraphicsLayer;
                    GraphicsLayer newLayer = layer as GraphicsLayer;
                    if (newLayer != null && newLayer.Graphics.Count > 0)
                    {
                        if (currentLayer != null && LayerExtensions.GetGeometryType(currentLayer) == LayerExtensions.GetGeometryType(newLayer))
                        {
                            // Layers have the same geometry type - just copy the features from one to the other

                            newLayer.Graphics.MoveTo(currentLayer.Graphics);
                        }
                        else if (currentLayer != null && currentLayer.Graphics.Count == 0)
                        {
                            // Geometry types don't match, but the layer already added to the list doesn't have any
                            // features graphics.  Override the renderer from the added layer with that from the current
                            // one and copy over the features in the currently layer.

                            currentLayer.Renderer = newLayer.Renderer;
                            newLayer.Graphics.MoveTo(currentLayer.Graphics);
                        }
                        else
                        {
                            // Geometry types don't match, but both layers have features.  We don't want to put the
                            // features in the same layer because that eliminates the ability to configure the layer's
                            // renderer.  So create separate layers.

                            // The layers will have the same name by default.  To avoid having multiple layers with the
                            // same name, append a suffix that indicates the geometry type, i.e. points, lines, or areas.
                            if (currentLayer != null)
                            {
                                currentLayer.AppendGeometryToLayerName();
                                featureCollectionLayerNames.Add(layer.DisplayName);
                            }
                            newLayer.AppendGeometryToLayerName();

                            // The layers will have the same ID by default, which can cause unexpected behavior.
                            // So give one of them a new ID.
                            newLayer.ID = Guid.NewGuid().ToString("N");
                            layers.Add(newLayer);

                            // Look in the web map's layers for other layers that have the same geometry type as the new
                            // layer.  Since the new layer has a new ID, and the logic here relies on ID to determine
                            // whether to merge with another layer, we need to update the IDs of the layers yet to be
                            // processed to match the new ID.
                            IEnumerable <Layer> others = allLayers.Where(
                                l => (l.ID == layer.ID) && LayerExtensions.GetGeometryType((GraphicsLayer)l) ==
                                LayerExtensions.GetGeometryType((GraphicsLayer)layer));

                            foreach (GraphicsLayer gLayer in others)
                            {
                                gLayer.ID = newLayer.ID;
                            }
                        }
                    }
                }
            }
            #region Get Basemap Title
            if (basemapLayers.Count > 0 && e.DocumentValues.ContainsKey("baseMap"))
            {
                IDictionary <string, object> dict = e.DocumentValues["baseMap"] as IDictionary <string, object>;
                if (dict != null)
                {
                    string baseMapTitle = "Basemap";
                    if (dict.ContainsKey("title"))
                    {
                        baseMapTitle = dict["title"] as string;
                        if (!string.IsNullOrWhiteSpace(baseMapTitle))
                        {
                            LayerExtensions.SetLayerName(basemapLayers[0], baseMapTitle);
                        }
                    }
                    //Mark reference layers
                    if (basemapLayers.Count > 1)
                    {
                        for (int i = 1; i < basemapLayers.Count; i++)
                        {
                            LayerExtensions.SetIsReferenceLayer(basemapLayers[i], true);
                            //Do not show in map contents
                            ESRI.ArcGIS.Client.Extensibility.LayerProperties.SetIsVisibleInMapContents(basemapLayers[i], false);
                        }
                    }
                }
            }
            #endregion

            e.Map.Layers.Clear();
            foreach (Layer layer in layers)
            {
                if (onLayerInitFailed != null)
                {
                    layer.InitializationFailed += onLayerInitFailed;
                }
                map.Layers.Add(layer);
            }

            #region Get map items and add any notes
            if (e.DocumentValues != null)
            {
                foreach (KeyValuePair <string, object> pair in e.DocumentValues)
                {
                    if (pair.Key == "MapItems")
                    {
                        List <GraphicsLayer> noteLayers = new List <GraphicsLayer>();
                        #region Get note layers
                        List <object> items = pair.Value as List <object>;
                        if (items == null)
                        {
                            continue;
                        }
                        foreach (var item in items)
                        {
                            IDictionary <string, object> dict = item as IDictionary <string, object>;
                            if (dict != null)
                            {
                                #region If note, add to notelayers
                                if (dict.ContainsKey("__type") && dict["__type"].ToString() == "Note:#ESRI.ArcGIS.Mapping.Controls.ArcGISOnline")
                                {
                                    if (dict.ContainsKey("Geometry") && dict.ContainsKey("Name"))
                                    {
                                        string name = dict["Name"] as string;
                                        IDictionary <string, object> gDict = dict["Geometry"] as IDictionary <string, object>;
                                        if (gDict == null)
                                        {
                                            continue;
                                        }
                                        ESRI.ArcGIS.Client.Geometry.Geometry geometry = null;
                                        if (gDict.ContainsKey("__type") && gDict["__type"] is string)
                                        {
                                            if (gDict["__type"].ToString() == "point:#ESRI.ArcGIS.Client.Geometry")
                                            {
                                                geometry = CreatePoint(gDict);
                                            }
                                            else if (gDict["__type"].ToString() == "Polyline:#ESRI.ArcGIS.Client.Geometry")
                                            {
                                                if (gDict.ContainsKey("paths") && gDict["paths"] is List <object> )
                                                {
                                                    List <object> paths = gDict["paths"] as List <object>;
                                                    Polyline      line  = new Polyline();
                                                    if (paths != null)
                                                    {
                                                        foreach (object path in paths)
                                                        {
                                                            List <object> points = path as List <object>;
                                                            ESRI.ArcGIS.Client.Geometry.PointCollection pts = new ESRI.ArcGIS.Client.Geometry.PointCollection();
                                                            foreach (object point in points)
                                                            {
                                                                if (point is IDictionary <string, object> )
                                                                {
                                                                    pts.Add(CreatePoint(point as IDictionary <string, object>));
                                                                }
                                                            }
                                                            line.Paths.Add(pts);
                                                        }
                                                        geometry = line;
                                                    }
                                                }
                                            }
                                            else if (gDict["__type"].ToString() == "Polygon:#ESRI.ArcGIS.Client.Geometry")
                                            {
                                                if (gDict.ContainsKey("rings") && gDict["rings"] is List <object> )
                                                {
                                                    List <object> rings = gDict["rings"] as List <object>;
                                                    Polygon       gon   = new Polygon();
                                                    if (rings != null)
                                                    {
                                                        foreach (object ring in rings)
                                                        {
                                                            List <object> points = ring as List <object>;
                                                            ESRI.ArcGIS.Client.Geometry.PointCollection pts = new ESRI.ArcGIS.Client.Geometry.PointCollection();
                                                            foreach (object point in points)
                                                            {
                                                                if (point is IDictionary <string, object> )
                                                                {
                                                                    pts.Add(CreatePoint(point as IDictionary <string, object>));
                                                                }
                                                            }
                                                            gon.Rings.Add(pts);
                                                        }
                                                        geometry = gon;
                                                    }
                                                }
                                            }
                                        }
                                        if (geometry != null && gDict.ContainsKey("spatialReference"))
                                        {
                                            IDictionary <string, object> srDict = gDict["spatialReference"] as IDictionary <string, object>;
                                            if (srDict != null)
                                            {
                                                if (srDict.ContainsKey("wkid"))
                                                {
                                                    geometry.SpatialReference = new SpatialReference()
                                                    {
                                                        WKID = Int32.Parse(srDict["wkid"].ToString())
                                                    }
                                                }
                                                ;
                                                else if (srDict.ContainsKey("wkt"))
                                                {
                                                    geometry.SpatialReference = new SpatialReference()
                                                    {
                                                        WKT = srDict["wkt"].ToString()
                                                    }
                                                }
                                                ;
                                            }
                                        }
                                        if (geometry != null)
                                        {
                                            GraphicsLayer glayer = ESRI.ArcGIS.Mapping.Controls.ArcGISOnline.Note.CreateGraphicsLayer(name, new Graphic()
                                            {
                                                Geometry = geometry
                                            }, map);
                                            if (dict.ContainsKey("Visible"))
                                            {
                                                bool visible = true;
                                                try
                                                {
                                                    visible = (bool)(dict["Visible"]);
                                                }
                                                catch { }
                                                glayer.Visible = visible;
                                            }
                                            noteLayers.Add(glayer);
                                        }
                                    }
                                }
                                #endregion
                            }
                        }
                        if (noteLayers.Count > 0)
                        {
                            for (int i = noteLayers.Count - 1; i >= 0; i--)
                            {
                                if (noteLayers[i] != null)
                                {
                                    map.Layers.Add(noteLayers[i]);
                                }
                            }
                        }
                        #endregion
                    }
                }
            }
            #endregion
        }