Exemple #1
0
        public static GeometryServiceOperationHelper GetProjectionHelper(EventHandler <ProjectGraphicsCompletedEventArgs> projectGraphicsCompleted, EventHandler <ProjectPointsCompletedEventArgs> projectPointsCompleted = null)
        {
            string geometryServiceUrl = new ConfigurationStoreHelper().GetGeometryServiceUrl(ConfigurationStoreProvider.DefaultConfigurationStore);

            if (string.IsNullOrEmpty(geometryServiceUrl))
            {
                System.Diagnostics.Debug.WriteLine("Must specify GeometryServiceUrl if spatial reference of the Map and the layer do not match");
                return(null);
            }
            GeometryServiceOperationHelper helper = new GeometryServiceOperationHelper(geometryServiceUrl);

            helper.ProjectGraphicsCompleted += projectGraphicsCompleted;
            helper.ProjectPointsCompleted   += projectPointsCompleted;

            return(helper);
        }
Exemple #2
0
        protected virtual void OnGraphicsCreated(GraphicCollection graphics, bool clearGraphics, EventHandler onGraphicsAddComplete)
        {
            if (graphics == null)
            {
                return;
            }

            if (MapSpatialReference == null || MapSpatialReference.Equals(LayerSpatialReference))
            {
                Graphics = graphics; // map spatial reference was unspecified => we assume points match the spatial ref of the match (responsbility is on the developer)
                OnUpdateCompleted(EventArgs.Empty);
                UpdateCursorForRenderer();
                if (onGraphicsAddComplete != null)
                {
                    onGraphicsAddComplete(this, EventArgs.Empty);
                }
            }
            else
            {
                GeometryServiceOperationHelper projectionHelper = GetProjectionHelper((s, e) =>
                {
                    if (clearGraphics)
                    {
                        Graphics = new GraphicCollection();
                    }
                    foreach (Graphic g2 in e.Graphics)
                    {
                        Graphics.Add(g2);
                    }
                    OnUpdateCompleted(EventArgs.Empty);
                    UpdateCursorForRenderer();
                    if (onGraphicsAddComplete != null)
                    {
                        onGraphicsAddComplete(this, EventArgs.Empty);
                    }
                });

                if (projectionHelper != null)
                {
                    projectionHelper.ProjectGraphics(graphics, MapSpatialReference);
                }
            }
        }
        void findNearbyToolWindow_FindNearby(object sender, FindNearbyEventArgs e)
        {
            if (Layer == null)
                return;

            GraphicsLayer graphicsLayer = Layer as GraphicsLayer;
            if (graphicsLayer == null)
                return;

            if (graphicsLayer.SelectionCount < 1)
            {
                findNearbyToolWindow.StopBusyIndicator();
                MessageBoxDialog.Show(Resources.Strings.MsgNoFeaturesSelected, Resources.Strings.ErrorCaption, MessageBoxButton.OK);
                return;
            }

            BufferParameters bufferParams = new BufferParameters();
            switch (e.LinearUnit)
            {
                case LinearUnit.Miles:
                    bufferParams.Unit = ESRI.ArcGIS.Client.Tasks.LinearUnit.StatuteMile;
                    break;
                case LinearUnit.Meters:
                    bufferParams.Unit = ESRI.ArcGIS.Client.Tasks.LinearUnit.Meter;
                    break;
                case LinearUnit.Kilometers:
                    bufferParams.Unit = ESRI.ArcGIS.Client.Tasks.LinearUnit.Kilometer;
                    break;
            }
            bufferParams.UnionResults = true;
            bufferParams.OutSpatialReference = Map.SpatialReference;
            SpatialReference gcs = new SpatialReference(4326);
            bufferParams.BufferSpatialReference = gcs;
            bufferParams.Geodesic = true;
            bufferParams.Distances.Add(e.Distance);

            // Check the spatial reference of the first graphic
            Graphic firstGraphic = graphicsLayer.SelectedGraphics.ElementAt(0);
            bool isInGcs = firstGraphic.Geometry != null
                             && firstGraphic.Geometry.SpatialReference != null
                             && firstGraphic.Geometry.SpatialReference.Equals(gcs);

            // In order to perform geodesic buffering we need to pass geometries in GCS to the geom service
            if (isInGcs)
            {
                foreach (Graphic selectedGraphic in graphicsLayer.SelectedGraphics)
                    bufferParams.Features.Add(selectedGraphic);

                buffer(GeometryServiceUrl, bufferParams, e);
            }
            else
            {
                GeometryServiceOperationHelper helper = new GeometryServiceOperationHelper(GeometryServiceUrl);
                helper.ProjectGraphicsCompleted += (o, args) => {
                    foreach (Graphic selectedGraphic in args.Graphics)
                        bufferParams.Features.Add(selectedGraphic);
                    buffer(GeometryServiceUrl, bufferParams, e);
                };
                helper.ProjectGraphics(graphicsLayer.SelectedGraphics.ToList(), new SpatialReference(4326));
            }
        }        
        private void switchBaseMapLayer(TiledMapServiceLayer baseMapLayer, Envelope newExtent, List<Layer> oldBasemapLayers)
        {
            if (Map == null)
                return;

            // 1. Save the operational layers (We assume a single base layer)
            System.Collections.Generic.Stack<Layer> layers = new System.Collections.Generic.Stack<Layer>();
            for (int i = Map.Layers.Count - 1; i >= 0; i--)
            {
                Layer l = Map.Layers[i];
                if (oldBasemapLayers.Contains(l))
                    continue;

                Map.Layers.RemoveAt(i);
                layers.Push(l);
            }

            // 2. Clear the layers collection
            Map.Layers.Clear();

            // 3. Set the extent
            bool spatialReferenceUnchanged = Map.SpatialReference.Equals(newExtent.SpatialReference);
            Map.Extent = newExtent;

            // 4a. Set layer id if this is not set
            if (string.IsNullOrEmpty(baseMapLayer.ID) || (!string.IsNullOrEmpty(baseMapLayer.ID) && Map.Layers[baseMapLayer.ID] != null))
                baseMapLayer.ID = Guid.NewGuid().ToString("N");

            // 4. Add the new base map
            Map.Layers.Add(baseMapLayer);

            // 5. Re-add the operational layers         
            while (layers.Count > 0)
            {
                Layer layer = layers.Pop();
                if (!spatialReferenceUnchanged)
                {
                    //reproject graphics layers that are not feature layers 
                    // Feature layers support reprojection
                    if (layer is GraphicsLayer && !(layer is FeatureLayer))
                    {
                        GraphicsLayer graphicsLayer = layer as GraphicsLayer;
                        if (graphicsLayer.Graphics.Count > 0)
                        {
                            GeometryServiceOperationHelper helper = new GeometryServiceOperationHelper(
                                                                                                        new ConfigurationStoreHelper().GetGeometryServiceUrl(ConfigurationStore));
                            helper.ProjectGraphicsCompleted += (o, e) =>
                            {
                                GraphicsLayer targetLayer = e.UserState as GraphicsLayer;
                                if (targetLayer != null)
                                {
                                    targetLayer.Graphics.Clear();
                                    foreach (Graphic graphic in e.Graphics)
                                        targetLayer.Graphics.Add(graphic);
                                }
                            };
                            helper.ProjectGraphics(graphicsLayer.Graphics, newExtent.SpatialReference, graphicsLayer);
                        }

                        // update the map spatial reference on custom layers
                        ICustomGraphicsLayer customGraphicsLayer = layer as ICustomGraphicsLayer;
                        if (customGraphicsLayer != null)
                            customGraphicsLayer.MapSpatialReference = Map.SpatialReference;
                        else
                        {
                            HeatMapLayerBase heatMapLayer = layer as HeatMapLayerBase;
                            if (heatMapLayer != null)
                                heatMapLayer.MapSpatialReference = Map.SpatialReference;
                        }
                    }
                    else
                    {
                        HeatMapLayerBase heatMapLayer = layer as HeatMapLayerBase;
                        if (heatMapLayer != null && heatMapLayer.HeatMapPoints.Count > 0)
                        {
                            GeometryServiceOperationHelper helper = new GeometryServiceOperationHelper(new ConfigurationStoreHelper().GetGeometryServiceUrl(ConfigurationStore));
                            helper.ProjectPointsCompleted += (o, e) =>
                            {
                                PointCollection points = new PointCollection();

                                foreach (MapPoint item in e.Points)
                                {
                                    if (item != null)
                                        points.Add(item);
                                }

                                heatMapLayer.HeatMapPoints = points;
                                heatMapLayer.MapSpatialReference = points[0].SpatialReference;
                                heatMapLayer.Refresh();
                            };
                            helper.ProjectPoints(heatMapLayer.HeatMapPoints, newExtent.SpatialReference);
                        }
                    }
                }
                Map.Layers.Add(layer);
            }
        }
        private void CreateNewBaseMapWithSpatialReference(Envelope targetInitialExtent, Envelope targetFullExtent, BaseMapInfo baseMapInfo, SpatialReference targetServiceSpatialReference)
        {
            // Reproject oldMap's extent before comparison
            GeometryServiceOperationHelper geomHelper = new GeometryServiceOperationHelper(
                            new ConfigurationStoreHelper().GetGeometryServiceUrl(ConfigurationStore),
                            baseMapInfo.UseProxy ? baseMapInfo.ProxyUrl : null);
            geomHelper.GeometryServiceOperationFailed += (o, args) =>
            {
                Logger.Instance.LogError(args.Exception);
                MessageBoxDialog.Show(ESRI.ArcGIS.Mapping.Controls.Resources.Strings.MsgUnableToAccessGeometryService + Environment.NewLine + args.Exception != null ? args.Exception.Message : ESRI.ArcGIS.Mapping.Controls.Resources.Strings.MsgUnknownError);
            };
            geomHelper.ProjectExtentCompleted += (o, args) =>
            {
                Envelope targetExtent = null;
                // If the extents (compared in same projection) interesect, set the extent of the new map to the projected extent
                if (targetInitialExtent != null)
                {
                    if (args.Extent.Intersects(targetInitialExtent))
                    {
                        if (isFullyContainedWithin(args.Extent, targetInitialExtent))
                            targetExtent = targetFullExtent; // if the full extent of the new service is fully within, automatically zoom to it
                        else
                            targetExtent = args.Extent;
                    }
                    else
                        targetExtent = targetInitialExtent;
                }
                else if (targetFullExtent != null)
                {
                    if (args.Extent.Intersects(targetFullExtent))
                    {
                        if (isFullyContainedWithin(args.Extent, targetFullExtent))
                            targetExtent = targetFullExtent; // if the full extent of the new service is fully within, automatically zoom to it
                        else
                            targetExtent = args.Extent;
                    }
                    else
                        targetExtent = targetFullExtent;
                }

                // else don't set an extent
                // the map will default to the full extent of the service

                // Since map will not be in a different projection, we have to re-create the map
                BaseMapInfo targetBaseMapInfo = baseMapInfo;
                IBaseMapDataSource dataSoure = DataSourceProvider.CreateDataSourceForBaseMapType(targetBaseMapInfo.BaseMapType) as IBaseMapDataSource;
                if (dataSoure == null)
                    throw new Exception(string.Format(ESRI.ArcGIS.Mapping.Controls.Resources.Strings.ExceptionDatasourceNotLoadedForBaseMapType, targetBaseMapInfo.BaseMapType.ToString()));
                TiledMapServiceLayer layer = dataSoure.CreateBaseMapLayer(targetBaseMapInfo);
                layer.SetValue(ESRI.ArcGIS.Client.WebMap.Document.IsBaseMapProperty, true);
                layer.SetValue(ESRI.ArcGIS.Client.Extensibility.MapApplication.LayerNameProperty, targetBaseMapInfo.DisplayName);
                checkAndEnsureBingMapsTokenIfRequired(layer);

                // Save current selected layer
                Layer currentSelectedLayer = SelectedLayer;

                saveGraphicsInViewForSelectedLayerInAttributeDisplay();

                // Disable listening for layer changed events because we are re-adding layers to the collection. The initialization events are not fired nor is symbology changed
                Map.Layers.CollectionChanged -= Layers_CollectionChanged;

                List<Layer> oldBaseMapLayers = new List<Layer>();
                foreach (Layer l in Map.Layers)
                {
                    if ((bool)l.GetValue(ESRI.ArcGIS.Client.WebMap.Document.IsBaseMapProperty))
                        oldBaseMapLayers.Add(l);
                }

                switchBaseMapLayer(layer, targetExtent, oldBaseMapLayers);

                // Re-Enable listening for layer changed events
                Map.Layers.CollectionChanged += Layers_CollectionChanged;

                // Restore current selected layer
                SelectedLayer = currentSelectedLayer;

                restoreGraphicsInViewForSelectedLayerInAttributeDisplay();

                OnNewMapCreated(new MapRecreatedEventArgs() { NewMap = Map });
                OnBaseMapChangeComplete(EventArgs.Empty);
            };
            geomHelper.ProjectExtent(Map.Extent, targetServiceSpatialReference);
        }
        public void ZoomMapToExtent(Envelope env)
        {
            if (env == null || Map == null)
                return;

            if (!mapInitComplete)
                throw new InvalidOperationException(ESRI.ArcGIS.Mapping.Controls.Resources.Strings.ExceptionCannotCallZoomMapToExtentBeforeMapHasInitialized);

            if (Map.SpatialReference == null)
                throw new InvalidOperationException(ESRI.ArcGIS.Mapping.Controls.Resources.Strings.ExceptionCannotCallZoomMapToExtentBeforeMapHasInitializedMapReferenceNull);

            if (env.SpatialReference == null)
                throw new ArgumentException(ESRI.ArcGIS.Mapping.Controls.Resources.Strings.ExceptionMustSpecifySpatialReferenceOnEnvelope);

            if (Map.SpatialReference.Equals(env.SpatialReference))
            {
                Map.Extent = env;
            }
            else
            {
                GeometryServiceOperationHelper geomHelper = new GeometryServiceOperationHelper(
                                                                                                                new ConfigurationStoreHelper().GetGeometryServiceUrl(ConfigurationStore));
                geomHelper.GeometryServiceOperationFailed += (o, args) =>
                {
                    Logger.Instance.LogError(args.Exception);
                    throw args.Exception;
                };
                geomHelper.ProjectExtentCompleted += (o, args) =>
                {
                    Map.Extent = args.Extent;
                };
                geomHelper.ProjectExtent(env, Map.SpatialReference);
            }
        }
        private void PerformPostLayerInitializationActions(Layer layer, bool initializationSuccess)
        {
            GraphicsLayer gLayer = layer as GraphicsLayer;
            if (gLayer != null)
            {
                GeometryType geometryType = Core.LayerExtensions.GetGeometryType(gLayer);
                Collection<FieldInfo> layerFields = Core.LayerExtensions.GetFields(gLayer);
                FeatureLayer featureLayer = layer as FeatureLayer;
                if (layerFields.Count == 0 &&
                    featureLayer != null && featureLayer.LayerInfo != null && featureLayer.LayerInfo.Fields != null)
                {
                    foreach (ESRI.ArcGIS.Client.Field field in featureLayer.LayerInfo.Fields)
                    {
                        if (FieldHelper.IsFieldFilteredOut(field.Type))
                            continue;
                        ESRI.ArcGIS.Mapping.Core.FieldInfo fieldInfo = ESRI.ArcGIS.Mapping.Core.FieldInfo.FieldInfoFromField(featureLayer, field);
                        layerFields.Add(fieldInfo);
                    }
                }
                if (gLayer.Graphics != null)
                {
                    #region Get geometry type, start getting symbology
                    if (geometryType == GeometryType.Unknown && gLayer.Graphics.Count > 0)
                    {
                        geometryType = LayerUtils.GetGeometryTypeFromGraphic(gLayer.Graphics.ElementAtOrDefault(0));
                        Core.LayerExtensions.SetGeometryType(gLayer, geometryType);

                        if ((gLayer.Renderer == null || gLayer.Renderer is HiddenRenderer) && !Symbology.DefaultSymbols.ContainsKey(geometryType))
                        {
                            if (geometryType == GeometryType.Unknown)
                            {
                                gLayer.SetValue(ESRI.ArcGIS.Client.Extensibility.LayerExtensions.ErrorMessageProperty, "Layer has unspecified geometry type.");
                            }
                            else
                            {
                                Core.LayerExtensions.SetRunLayerPostInitializationActions(gLayer, true);
                                SymbolConfigProvider.GetDefaultLinearGradientBrush(gLayer, ColorRampType.ClassBreaks);
                            }
                            return;
                        }
                    }
                    #endregion

                    #region Project graphics if necessary
                    if (graphicsRequireReprojection(gLayer.Graphics))
                    {
                        GeometryServiceOperationHelper helper = new GeometryServiceOperationHelper(
                             new ConfigurationStoreHelper().GetGeometryServiceUrl(ConfigurationStore)
                            );
                        helper.ProjectGraphicsCompleted += (sender, args) =>
                        {
                            GraphicsLayer targetLayer = args.UserState as GraphicsLayer;
                            if (targetLayer != null)
                            {
                                targetLayer.Graphics.Clear();
                                foreach (Graphic graphic in args.Graphics)
                                    targetLayer.Graphics.Add(graphic);
                            }
                        };
                        helper.ProjectGraphics(gLayer.Graphics, Map.SpatialReference, gLayer);
                    }
                    #endregion

                    #region Get field information
                    if (layerFields.Count == 0) // fields not determined yet
                    {
                        determineFieldsFromGraphic(layerFields, gLayer.Graphics.ElementAtOrDefault(0));
                    }
                    #endregion
                }

                #region Get renderer from feature layer's layer info, if necessary
                if (gLayer.Renderer == null || gLayer.Renderer is HiddenRenderer)
                {
                    FeatureLayer lay = gLayer as FeatureLayer;
                    if (lay != null && lay.LayerInfo != null && lay.LayerInfo.Renderer != null)
                    {
                        lay.Renderer = lay.LayerInfo.Renderer;
                    }
                }
                #endregion

                #region Change PictureMarkerSymbol to ImageFillSymbol
                if (gLayer.Renderer != null && (geometryType == GeometryType.Point || geometryType == GeometryType.MultiPoint))
                {
                    SimpleRenderer sr = gLayer.Renderer as SimpleRenderer;
                    ESRI.ArcGIS.Client.FeatureService.Symbols.PictureMarkerSymbol pms = null;
                    if (sr != null)
                    {
                        pms = sr.Symbol as ESRI.ArcGIS.Client.FeatureService.Symbols.PictureMarkerSymbol;
                        if (pms != null)
                            sr.Symbol = SymbolJsonHelper.ToImageFillSymbol(pms);
                    }
                    else
                    {
                        ClassBreaksRenderer cbr = gLayer.Renderer as ClassBreaksRenderer;
                        if (cbr != null)
                        {
                            foreach (ClassBreakInfo info in cbr.Classes)
                            {
                                pms = info.Symbol as ESRI.ArcGIS.Client.FeatureService.Symbols.PictureMarkerSymbol;
                                if (pms != null)
                                    info.Symbol = SymbolJsonHelper.ToImageFillSymbol(pms);
                            }
                        }
                        else
                        {
                            UniqueValueRenderer uvr = gLayer.Renderer as UniqueValueRenderer;
                            if (uvr != null)
                            {
                                foreach (UniqueValueInfo info in uvr.Infos)
                                {
                                    pms = info.Symbol as ESRI.ArcGIS.Client.FeatureService.Symbols.PictureMarkerSymbol;
                                    if (pms != null)
                                        info.Symbol = SymbolJsonHelper.ToImageFillSymbol(pms);
                                }
                            }
                        }
                    }
                }
                #endregion

                if (gLayer.Renderer == null || gLayer.Renderer is HiddenRenderer)
                    ApplyDefaultRenderer(gLayer, geometryType);

                ApplyDefaultGradientBrush(gLayer);
            }
            else if ((layer is ArcGISDynamicMapServiceLayer || layer is ArcGISTiledMapServiceLayer)
                && !((bool)layer.GetValue(ESRI.ArcGIS.Client.WebMap.Document.IsBaseMapProperty)))
            {
                //get layer infos - used later for figuring out domain/subtypes, etc
                if ((layer.GetValue(ESRI.ArcGIS.Mapping.Core.LayerExtensions.LayerInfosProperty) as Collection<LayerInformation>)
                    == null)
                    getLayerInfos(layer);
            }
            bool doSelect = false;
            layer.SetValue(ESRI.ArcGIS.Client.Extensibility.LayerExtensions.InitialUpdateCompletedProperty, true);
            if (!initializationSuccess)
                layer.SetValue(ESRI.ArcGIS.Client.Extensibility.LayerExtensions.InitialUpdateFailedProperty, true);
            else
            {
                bool hasId = !string.IsNullOrEmpty(layer.ID) || !string.IsNullOrEmpty(layer.GetValue(ESRI.ArcGIS.Client.Extensibility.MapApplication.LayerNameProperty) as  string);
                // Certain layers get added when the map draw mode is changed (An empty graphics layer is added)
                // We don't want to auto-select this layer
                if (hasId || !(layer is GraphicsLayer))
                    doSelect = true;
            }

            if (doSelect)
                SetSelectedLayer(new LayerEventArgs() { Layer = layer });

            SubscribeToLayerInitializationEvents(layer, false);
        }
        public override void Execute(object parameter)
        {
            if (Layer == null)
                return;
            bool isServerLayer = false;
            Envelope targetExtent = null;
            TiledLayer tiledLayer = Layer as TiledLayer;
            if (tiledLayer != null)
            {
                isServerLayer = true;
                targetExtent = LayerExtentExtensions.GetTiledLayerFullExtent(tiledLayer); // get the cached value (if any) which will likely be in the map's spRef already
                if (targetExtent == null) // value not known, use value on service metadata (will likely be in the services' spatial ref and not neccesarily in map's spRef)
                    targetExtent = tiledLayer.FullExtent;
                if (tiledLayer is ESRI.ArcGIS.Client.Bing.TileLayer)
                {
                    if (targetExtent.SpatialReference == null)
                        targetExtent.SpatialReference = new SpatialReference(102100);
                }
            }

            DynamicLayer dynamicLayer = Layer as DynamicLayer;
            if (dynamicLayer != null)
            {
                isServerLayer = true;
                targetExtent = LayerExtentExtensions.GetDynamicLayerFullExtent(dynamicLayer); // get the cached value (if any) which will likely be in the map's spRef already
                if (targetExtent == null)// value not known, use value on service metadata (will likely be in the services' spatial ref and not neccesarily in map's spRef)
                    targetExtent = dynamicLayer.FullExtent;
            }

            if (isServerLayer)
            {
                if (targetExtent == null || Map == null || Map.SpatialReference == null)
                    return;

                if (Map.SpatialReference.Equals(targetExtent.SpatialReference))
                {
                    // spatial reference matches. can directly zoom
                    Map.ZoomTo(targetExtent);
                }
                else
                {
                    if (string.IsNullOrEmpty(GeometryServiceUrl))
                        throw new Exception(Resources.Strings.ExceptionNoGeometryServiceUrlSpecifiedLayerZoomedIsDifferentSpatialReference);

                    GeometryServiceOperationHelper helper = new GeometryServiceOperationHelper(GeometryServiceUrl);
                    helper.ProjectExtentCompleted += (o, e) =>
                    {
                        // Cache (save) the projected extent values
                        if (tiledLayer != null)
                            LayerExtentExtensions.SetTiledLayerFullExtent(tiledLayer, e.Extent);
                        else if (dynamicLayer != null)
                            LayerExtentExtensions.SetDynamicLayerFullExtent(dynamicLayer, e.Extent);
                        Map.ZoomTo(e.Extent);
                    };
                    helper.ProjectExtent(targetExtent, Map.SpatialReference);
                }
                return;
            }


            // Non server rendererd layers follow

            GraphicsLayer graphicsLayer = Layer as GraphicsLayer;
            if (graphicsLayer == null)
                return;

            if (Map != null)
            {
                Envelope newMapExtent = null;
                if (graphicsLayer.Graphics.Count < 1)
                {
                    FeatureLayer featureLayer = graphicsLayer as FeatureLayer;
                    if (featureLayer != null && featureLayer.LayerInfo != null && featureLayer.LayerInfo.Extent != null)
                    {
                        Envelope env = featureLayer.LayerInfo.Extent;

                        SpatialReference sr = env.SpatialReference;
                        if (sr == null)
                            sr = featureLayer.LayerInfo.DefaultSpatialReference;

                        if (Map.SpatialReference.Equals(sr))
                        {
                            Map.PanTo(env);
                        }
                        else if (sr != null)
                        {
                            GeometryServiceOperationHelper geomHelper = new GeometryServiceOperationHelper(
                                new ConfigurationStoreHelper().GetGeometryServiceUrl(View.Instance.ConfigurationStore));
                            geomHelper.GeometryServiceOperationFailed += (o, args) =>
                            {
                                Logger.Instance.LogError(args.Exception);
                                throw args.Exception;
                            };
                            geomHelper.ProjectExtentCompleted += (o, args) =>
                            {
                                MapZoomOrPan(args.Extent);
                            };
                            geomHelper.ProjectExtent(env, Map.SpatialReference);
                        }
                    }
                }
                else
                {
                    foreach (Graphic graphic in graphicsLayer.Graphics)
                    {
                        if (graphic.Geometry != null && graphic.Geometry.Extent != null)
                            newMapExtent = graphic.Geometry.Extent.Union(newMapExtent);
                    }
                    newMapExtent = MapZoomOrPan(newMapExtent);
                }
            }
        }
        public static GeometryServiceOperationHelper GetProjectionHelper(EventHandler<ProjectGraphicsCompletedEventArgs> projectGraphicsCompleted, EventHandler<ProjectPointsCompletedEventArgs> projectPointsCompleted = null)
        {
            string geometryServiceUrl = new ConfigurationStoreHelper().GetGeometryServiceUrl(ConfigurationStoreProvider.DefaultConfigurationStore);
            if (string.IsNullOrEmpty(geometryServiceUrl))
            {
                System.Diagnostics.Debug.WriteLine("Must specify GeometryServiceUrl if spatial reference of the Map and the layer do not match");
                return null;
            }
            GeometryServiceOperationHelper helper = new GeometryServiceOperationHelper(geometryServiceUrl);
            helper.ProjectGraphicsCompleted += projectGraphicsCompleted;
            helper.ProjectPointsCompleted += projectPointsCompleted;

            return helper;
        }