/// <summary>
        /// Zoom map to a feature layer's extent. If its SR is different than the base map's, re-project the extent
        /// </summary>
        private void MenuItemZoomTo_Click(object sender, MenuItemClickEventArgs e)
        {
            HideConextMenu();

            if (e.ItemTag is LivingMapLayer)
            {
                LivingMapLayer mapConfig = e.ItemTag as LivingMapLayer;
                Envelope       extent    = this.MapControl.Layers[mapConfig.ID].FullExtent;
                if (!SpatialReference.AreEqual(extent.SpatialReference, this.MapControl.SpatialReference, false))
                {
                    GeometryTool.ProjectEnvelope(this.AppConfig.GeometryService, extent, this.MapSRWKID, (s, g) =>
                    {
                        if (g.ProjectedGeometry != null)
                        {
                            this.MapControl.ZoomTo(g.ProjectedGeometry);
                        }
                    });
                }
                else
                {
                    this.MapControl.ZoomTo(extent);
                }
            }
            else if (e.ItemTag is TOCNodeInfo)
            {
                TOCNodeInfo nodeInfo = e.ItemTag as TOCNodeInfo;
                if (nodeInfo.LayerExtent == null)
                {
                    this.IsBusy = true;
                    Layer  layer    = this.MapControl.Layers[nodeInfo.MapID];
                    string layerUrl = (nodeInfo.IsTiledMap) ? (layer as ArcGISTiledMapServiceLayer).Url : (layer as ArcGISDynamicMapServiceLayer).Url;
                    ArcGISLayerInfoReader layerInfoReader = new ArcGISLayerInfoReader(layerUrl + "/" + nodeInfo.LayerID);
                    layerInfoReader.InfoReady += (obj, arg) =>
                    {
                        if (!SpatialReference.AreEqual(arg.LayerInfo.Extent.SpatialReference, this.MapControl.SpatialReference, false))
                        {
                            GeometryTool.ProjectEnvelope(this.AppConfig.GeometryService, arg.LayerInfo.Extent, this.MapSRWKID, (s, g) =>
                            {
                                this.IsBusy = false;
                                if (g.ProjectedGeometry != null)
                                {
                                    nodeInfo.LayerExtent = g.ProjectedGeometry as Envelope;
                                    this.MapControl.ZoomTo(nodeInfo.LayerExtent);
                                }
                            });
                        }
                        else
                        {
                            this.IsBusy          = false;
                            nodeInfo.LayerExtent = nodeInfo.LayerExtent = arg.LayerInfo.Extent;
                            this.MapControl.ZoomTo(nodeInfo.LayerExtent);
                        }
                    };
                }
                else
                {
                    this.MapControl.ZoomTo(nodeInfo.LayerExtent);
                }
            }
        }
        /// <summary>
        /// Toggle the visibility of a feature layer in an ArcGIS Dynamic Map Service Layer
        /// </summary>
        private void OnToggleFeatureLayer(object sender, RoutedEventArgs e)
        {
            HideConextMenu();

            TOCNodeInfo  nodeInfo = null;
            TreeViewItem treeNode = null;

            if (sender is CheckBox)
            {
                CheckBox checkBox = sender as CheckBox;
                treeNode = checkBox.Tag as TreeViewItem;
                nodeInfo = treeNode.Tag as TOCNodeInfo;
            }
            else if (sender is RadioButton)
            {
                RadioButton radioBox = sender as RadioButton;
                treeNode = radioBox.Tag as TreeViewItem;
                nodeInfo = treeNode.Tag as TOCNodeInfo;
            }

            if (treeNode != null && nodeInfo != null)
            {
                TreeViewItem mapNode = GetMapLayerNode(treeNode);
                ArcGISDynamicMapServiceLayer dynamicLayer = this.MapControl.Layers[nodeInfo.MapID] as ArcGISDynamicMapServiceLayer;
                int[] oldVisibles = (int[])dynamicLayer.VisibleLayers.Clone();

                List <int> visLayers = new List <int>();
                GetVisibleLayerIDs(mapNode, visLayers);
                dynamicLayer.VisibleLayers = visLayers.ToArray();
                EventCenter.DispatchMapLayerVisibilityChangeEvent(this, new MapLayerVisibilityChangeEventArgs(dynamicLayer, oldVisibles));
            }
        }
        /// <summary>
        /// Get Visible Layer IDs in a Dynamic Map Service
        /// </summary>
        private void GetVisibleLayerIDs(TreeViewItem layerNode, List <int> visLayers)
        {
            if (layerNode.HasItems)
            {
                foreach (object item in layerNode.Items)
                {
                    if (item is TreeViewItem)
                    {
                        TreeViewItem treeItem = item as TreeViewItem;
                        TOCNodeInfo  nodeInfo = treeItem.Tag as TOCNodeInfo;

                        if (treeItem.Header is CheckBox)
                        {
                            CheckBox checkBox = treeItem.Header as CheckBox;

                            if (checkBox.IsChecked.Value && checkBox.Tag is TreeViewItem)
                            {
                                if (nodeInfo.IsGroupLayer) // Get SubLayers' Visibilities
                                {
                                    GetVisibleLayerIDs(checkBox.Tag as TreeViewItem, visLayers);
                                }
                                else
                                {
                                    visLayers.Add(nodeInfo.LayerID);
                                }
                            }
                        }
                        else if (treeItem.Header is RadioButton)
                        {
                            RadioButton radioBox = treeItem.Header as RadioButton;

                            if (radioBox.IsChecked.Value && radioBox.Tag is TreeViewItem)
                            {
                                if (nodeInfo.IsGroupLayer) // Get SubLayers' Visibilities
                                {
                                    GetVisibleLayerIDs(radioBox.Tag as TreeViewItem, visLayers);
                                }
                                else
                                {
                                    visLayers.Add(nodeInfo.LayerID);
                                }
                            }
                        }
                    }
                }
            }
        }