Select to view content in your preferred language

ArcGis "Zoom To Layer" functionality in ESRI Silverlight API

4625
12
07-28-2010 12:03 PM
AlexanderOvsyankin
Deactivated User
Hello Experts,

I have sde database and I published a dynamic service with 1 layer in it. The layer displaying data from sde spatial view.

When my map is initializing I want to zoom to the layer extent (extent of all features in this layer).

I have some options on how to do it:
1. Set full extent for the Data Frame in mxd before publishing and then zoom to
ArcGISDynamicMapServiceLayer.FullExtent. It's not a good aproach for me since it is a dynamic service and data are loading to sde by another application, so after data will arrive this extent will not be actual.

2. Set current extent in mxd to full layer extent before publishing and then zoom to
ArcGISDynamicMapServiceLayer.InitialExtent. It's not a good aproach again due to the same reason as described above.

3. Run query against the layer, get features, go throw the list of results and using feature.geometry - create an extent. But layer contains much more than 500 (recommended by ESRI amount of features to be returned by the query ) objects (~100 000) and in result my calculated extent will not present the real extent of data, but just a portion of it. Of course I can change the maximum amount of features to be returned by the query ;), but my map will be extremely slow since I will need to load all 100 000 features on the client side :(...

Additionally, I am filtering my layer using LayerDefinition and I want to be able to zoom into filtered layer too (in this case aproaches 1 and 2 don't work at all)...

4. Not sure, but: I can create my own geoprocessing service to get the extent of the layer on the server side and use it on the client side to zoom.

So the question is: Is there any other possibilities to Zoom to extent of all features in the layer? May be I missed something in the API reference?
0 Kudos
12 Replies
ChristopherHill
Deactivated User
if you wanted to get at the json of the sublayer information from REST you would need to preform a web request. Here s an example of populating the sublayers into a list box and then requesting the sublayer json based on id. When the json response returns I look for the extent json, check its spatial reference to make sure it matches my maps spatial reference then preform a zoom to the sub layers extent. This example is just to demostrate how to get the infomation for the sublayer REST endpoints.

Xaml
<Grid x:Name="LayoutRoot" Background="White">        
        <Grid.Resources>
            <DataTemplate x:Key="ListBoxItem">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding ID}" Margin="5,0" />
                    <TextBlock Text="{Binding Name}" Grid.Column="1" />
                </Grid>                                
            </DataTemplate>
        </Grid.Resources>
        <!--Map Control-->
        <esri:Map x:Name="esriMap">

            <!--Base Layer-->
            <esri:ArcGISTiledMapServiceLayer ID="baseLayer" 
                Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"/>

            <!--Dynamic Layer-->
            <esri:ArcGISDynamicMapServiceLayer ID="dynamicLayer" 
               Url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/WaterTemplate/WaterDistributionAdministrativeReport/MapServer" 
               Initialized="ArcGISDynamicMapServiceLayer_Initialized"/>

        </esri:Map>
        
        <ListBox x:Name="SubLayersListBox" 
                 ItemTemplate="{StaticResource ListBoxItem}"
                 SelectionChanged="SubLayersListBox_SelectionChanged" 
                 VerticalAlignment="Top" 
                 HorizontalAlignment="Right" />
    </Grid>


Code Behind
ArcGISDynamicMapServiceLayer dynamicLayer;
  WebClient wc;
  SpatialReference WEB_MERCATOR = new SpatialReference(102100);
  SpatialReference GEOGRAPHIC = new SpatialReference(4326);
  WebMercator projection = new WebMercator();
  
  public MainPage()
  {
   InitializeComponent();
   wc = new WebClient();
   wc.DownloadStringCompleted += wc_DownloadStringCompleted;
  }

  private void ArcGISDynamicMapServiceLayer_Initialized(object sender, EventArgs e)
  {
   dynamicLayer = esriMap.Layers["dynamicLayer"] as ArcGISDynamicMapServiceLayer;
   List<LayerInfo> sublayers = new List<LayerInfo>();
   foreach (LayerInfo ld in dynamicLayer.Layers)
   {        
    sublayers.Add(ld);
   }

   SubLayersListBox.ItemsSource = sublayers;
  }
  

  private void SubLayersListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
  {
   if (SubLayersListBox.SelectedIndex < 0) return;

   LayerInfo sublayerMetaData = SubLayersListBox.SelectedItem as LayerInfo;
   if (sublayerMetaData != null)
   {
    Uri uri = new Uri(string.Format("{0}/{1}?f=json",dynamicLayer.Url,sublayerMetaData.ID));
    if (wc.IsBusy)
     wc.CancelAsync();    

    if(!wc.IsBusy)
     wc.DownloadStringAsync(uri);
   }
  }

  void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  {
   if (e.Error != null)
   {
    MessageBox.Show(e.Error.Message);
    return;
   }
   JsonValue jValue = JsonObject.Parse(e.Result);
   if (jValue.ContainsKey("extent"))
   {
    string sExtent = jValue["extent"].ToString();
    using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(sExtent)))
    {
     DataContractJsonSerializer ds = new DataContractJsonSerializer(typeof(Envelope));
     Envelope extent = ds.ReadObject(ms) as Envelope;

     if (!extent.SpatialReference.Equals(WEB_MERCATOR))
     {
      if (extent.SpatialReference.Equals(GEOGRAPHIC))
      {
       esriMap.ZoomTo(projection.FromGeographic(extent));
      }
      else
      {
       MessageBox.Show("Need to project spatial reference.");
      }
     }
     else
      esriMap.ZoomTo(extent);
    };
   }
   
  }


Assemblies
System.ServiceModel.Web <- DataContractSerializer
System.Json <- JsonValue

Namespaces
using System;
using System.Collections.Generic;
using System.IO;
using System.Json;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using ESRI.ArcGIS.Client.Projection;
0 Kudos
SanajyJadhav
Deactivated User
How about just declaring one FeatureLayer and pass the url of your concerned layer (http://YourServer/ArcGIS/Rest/Services/ServiceName/MapSerer/layerIndex )to its constructor? Once it becomes the FeatureLayer, you can get its full extent.
0 Kudos
DominiqueBroux
Esri Frequent Contributor
How about just declaring one FeatureLayer and pass the url of your concerned layer (http://YourServer/ArcGIS/Rest/Services/ServiceName/MapSerer/layerIndex )to its constructor? Once it becomes the FeatureLayer, you can get its full extent.

You are right, that is a possible workaround, but you have to call by yourself the Initialize method of the FeatureLayer, then the layer infos will be available on event 'Layer.Initialized'.
0 Kudos