Select to view content in your preferred language

populating sublayers on a listbox along with the symbols

3069
23
02-09-2011 05:02 AM
SangamLama
Emerging Contributor
Hi all,
I'm following this tutorial to display and populate sublayers out of a dynamic map layer.
http://resources.esri.com/help/9.3/arcgisserver/apis/silverlight/samples/start.htm#SubLayerList

I figured it'd be cool to display the symbols representing those sublayers on the listbox, including the color fills symbols, line symbols etc. I was wondering how I could populate them?

The only time I've ever accessed low level details tied to every sublayer was when I carried out an IdentifyTask on certain coordinates (on the map). Then I used IdentifyResult to access the feature attributes. Would you say carrying out similar IdentifyTask is the only way? But again, the listbox is generated on application load, so I dont know how that's going to be possible..

Thanks for the ideas 🙂
0 Kudos
23 Replies
SangamLama
Emerging Contributor
Hi, again the example you provided generates the symbols for California map, but not for mine. I started to grow very suspicious about my own map server, so I looked into the code. I noticed that ImageSource always equals null for every layeritem!!

Also, I decided to compare these two map servers word per word. As far as the Airports layer is concerned (california map), it doesn't have any information about what kind of symbol is being used as you can see here

http://serverapps.esri.com/ArcGIS/rest/services/California/MapServer/0

And then I compared this layer to the Hydrants layer of my map server -- It has this Drawing Info section and it tells me what symbolizes a hydrant. Here's the information under that section:

Drawing Info:

Renderer:

Simple Renderer:
Symbol:

Picture Marker Symbol:
RIGHT HERE, THERE'S AN IMAGE OF A HYDRANT

Label:
Description:

Transparency: 0
Labeling Info:

Label Placement: esriServerPointLabelPlacementAboveRight
Label Expression: [Handle]
Use Coded Values: True
Symbol:

Simple Text Symbol:
Type: esriTS
Color:0, 0, 0, 255
Background Color: null
Border Line Color: null
Vertical Alignment: bottom
Horizontal Alignment: center
Right To Left: False
Angle: 0
XOffset: 0
YOffset: 0
Font Family: Arial
Font Size: 8
Font Style: normal
Font Weight: normal
Font Decoration: none

Min. Scale: 0
Max. Scale: 0

Even though this information is available, ImageSource still has a null value. So, should I assume that I should fetch this bit of source differently maybe?

Sorry I forgot to mention that if you have a hierarchy of group layers, you have also to adapt the C# code to take into account this hierarchy. 
  
Here is the code which should work whatever the number of group levels: 
void Legend_Refreshed(object sender, ESRI.ArcGIS.Client.Toolkit.Legend.RefreshedEventArgs e)
{
    SetLayerItemImageSource(e.LayerItem);
} 
 
private void SetLayerItemImageSource(LayerItemViewModel layerItem)
{
    if (layerItem.LegendItems != null && layerItem.LegendItems.Any()) // if there is a legend item
        layerItem.ImageSource = layerItem.LegendItems.First().ImageSource; // set the image of the sublayer with the image of the first legenditem
 
    // Call recursively SetLayerItemImageSource
    if (layerItem.LayerItems != null)
    {
        foreach(var sublayerItem in layerItem.LayerItems)
            SetLayerItemImageSource(sublayerItem);
    }
}
Note that instead of using your own listbox and a binding to a legend control, you can also retemplate the legend control to use a listbox. 
  
For example with this template: 
<esri:Legend Map="{Binding ElementName=MyMap}" LayerItemsMode="Flat" ShowOnlyVisibleLayers="False" LayerIDs="California" Refreshed="Legend_Refreshed">
<esri:Legend.Template>
 <ControlTemplate TargetType="esri:Legend">
  <ListBox ItemsSource="{TemplateBinding LayerItemsSource}" >
   <ListBox.ItemTemplate>
    <DataTemplate>
     <StackPanel Orientation="Horizontal">
      <CheckBox IsChecked="{Binding IsEnabled, Mode=TwoWay}" IsEnabled="{Binding IsInScaleRange}" VerticalAlignment="Center"/>
      <TextBlock Text="{Binding Label}" VerticalAlignment="Center"/>
      <Image Source="{Binding ImageSource}" Margin="3,0"/>
     </StackPanel>
    </DataTemplate>
   </ListBox.ItemTemplate>
  </ListBox>
 </ControlTemplate>
</esri:Legend.Template>
<esri:Legend>
you get this result:
0 Kudos
DominiqueBroux
Esri Frequent Contributor
Is a basic legend control (without any code, templating,..) working well with your service?

If answer is no, we have first to solve this issue (standard question in this case : which arcgis server version? is your service public or private?)

If answer is yes, it means that the imagesource is well initialized by the service. Then, the issue might come from the C# code I provided to initialize the imagesource of the layeritems.
Try to set a breakpoint on this line:
layerItem.ImageSource = layerItem.LegendItems.First().ImageSource; // set the image of the sublayer with the image of the first legenditem

and look at the imagesource initialized at this point.
0 Kudos
SangamLama
Emerging Contributor
Is a basic legend control (without any code, templating,..) working well with your service?.


- Yes, it did work.


If answer is yes, it means that the imagesource is well initialized by the service. Then, the issue might come from the C# code I provided to initialize the imagesource of the layeritems.
Try to set a breakpoint on this line:
layerItem.ImageSource = layerItem.LegendItems.First().ImageSource; // set the image of the sublayer with the image of the first legenditem

and look at the imagesource initialized at this point.



I put a breakpoint on that line, but the code never gets to it. I looked at values of all the properties in layerItem during the first SetLayerItemImageSource call, and here's what I got

{ESRI.ArcGIS.Client.Toolkit.MapLayerItem}
    [ESRI.ArcGIS.Client.Toolkit.MapLayerItem]: {ESRI.ArcGIS.Client.Toolkit.MapLayerItem}
    base {ESRI.ArcGIS.Client.Toolkit.Primitives.LegendItemViewModel}: {ESRI.ArcGIS.Client.Toolkit.MapLayerItem}
    BusyIndicatorVisibility: Visible
    IsBusy: true
    IsEnabled: true
    IsGroupLayer: false
    IsInScaleRange: true
    IsVisible: true
    Layer: {ESRI.ArcGIS.Client.ArcGISDynamicMapServiceLayer}
    LayerItems: Count = 11
    LayerItemsSource: Count = 11
    LayerType: "MapLayer Layer"
    LegendItems: null
    MaximumResolution: Infinity
    MinimumResolution: 0.0
    SubLayerID: 0

and on the successive recursive calls the items are null.
0 Kudos
DominiqueBroux
Esri Frequent Contributor
  
Yes, it did work. 
............. and on the successive recursive calls the items are null.  

I can't understand how the legend control could work well (i.e. the control displays the legend items with label+image) and at the same time, by code, the LegendItems are always null (i.e. looks like no swatches are returned by the legend service).

Is your map service public or private? (If public and if you want, send me your code dbroux@esri.com, I will take a look.)
0 Kudos
SangamLama
Emerging Contributor
I can't understand how the legend control could work well (i.e. the control displays the legend items with label+image) and at the same time, by code, the LegendItems are always null (i.e. looks like no swatches are returned by the legend service). 
  
Is your map service public or private? (If public and if you want, send me your code   dbroux@esri.com, I will take a look.)


Unfortunately its a private service. Although I am now very confirmed that the service itself needs a tweak somewhere before it will display the image. Because I found about 7 different publicly available services, and ran my application against them. I put

<esri2:Legend x:Name="mylegend" Map="{Binding ElementName=MyMap}"
LayerIDs="TownMapLayer"
LayerItemsMode="Tree"
ShowOnlyVisibleLayers="False"
BorderThickness="0"
Background="White"
>
on the xaml side and removed everything else. This displayed the labels and images for all of them. But with my service, it only displayed the labels.

I've contacted the person who administers our ArcGIS servers. I'll post an update if it's fixed.

Thanks for all your help 🙂
0 Kudos
DominiqueBroux
Esri Frequent Contributor
A reminder just in case... : for private services, the legend control needs ArcGIS server 10SP1 and can't work with previous versions.
0 Kudos
SangamLama
Emerging Contributor
A reminder just in case... : for private services, the legend control needs ArcGIS server 10SP1 and can't work with previous versions.


I still haven't solved this. i re-read the entire thread today, and would like to confirm something. So, the ArcGIS server we're running is 10. Does it strictly have to be 10SP1? If so, do you think that's the problem? Again, if so, any other way I can work this out other than with the Legend control?
0 Kudos
DominiqueBroux
Esri Frequent Contributor

So, the ArcGIS server we're running is 10. Does it strictly have to be 10SP1?


Yes ArcGIS server has to be 10SP1. Previous version of ArcGIS server don't provide any legend informations.



If so, do you think that's the problem?

For sure, it is.


Again, if so, any other way I can work this out other than with the Legend control?

The problem with private services previous to 10SP1 is that there is no way to get the swatches of the sublayers.
One option is you to write your legend service (using SOAP API), another option is you to upgrade your server to SP1.
0 Kudos
SangamLama
Emerging Contributor
now, let me confirm another thing. When you say a private service, you mean one that can't be accessed by anyone outside of my compan'y network. correct?

Also, I'll need some time to find some people in my office to confirm these, but, did anything under ArcGIS server 10 SP1 (private service) ever display such legends for other platforms? Or is it the case that ESRI never really supported such a feature in any platforms for public services? The reason I'm asking such a question  is because I just looked at our previous mapping application (9.3 ish), and found out that there's a legend that displays the images. Again, I'm just shooting in the dark, but, was MapServerLegendInfo ever a class that helped display the legend maybe?


Yes ArcGIS server has to be 10SP1. Previous version of ArcGIS server don't provide any legend informations.



For sure, it is.



The problem with private services previous to 10SP1 is that there is no way to get the swatches of the sublayers.
One option is you to write your legend service (using SOAP API), another option is you to upgrade your server to SP1.
0 Kudos
DominiqueBroux
Esri Frequent Contributor
When you say a private service, you mean one that can't be accessed by anyone outside of my compan'y network. correct?

Correct.
The legend fallback mechanism that is used by the legend control for services prior to 10SP1 is a service hosted by arcgis.com, so your service has to be accessible from arcgis.com ==> need to be public.


Also, I'll need some time to find some people in my office to confirm these, but, did anything under ArcGIS server 10 SP1 (private service) ever display such legends for other platforms? Or is it the case that ESRI never really supported such a feature in any platforms for public services?

The legend is still available by the SOAP API. If you are interested, there is a sample of a legend service using the SOAP API here : http://www.arcgis.com/home/item.html?id=c896e06026444819afcf47d11a1be730
0 Kudos