Hi I�??m hoping this thread is still open.I am looking to do something similar to what has been discussed here but my twist is instead of having the layers hard coded in the XAML I�??m looking to (1) have users enter the URL like here #AddLayerDynamically then (2)the Sublayers (including any hierarchy) would be listed with checkboxs like here #SubLayerList.This probably means most of the code will be done in codebehind c# then bound to respective elements in the XAMLI�??m very new to Silverlight. I�??ve been trying to do this for ages but no joy. Any help would be very much appreciated.
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:
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.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
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?
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.
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?
A reminder just in case... : for private services, the legend control needs ArcGIS server 10SP1 and can't work with previous versions.
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.)
Yes, it did work. ............. and on the successive recursive calls the items are null.
Is a basic legend control (without any code, templating,..) working well with your service?.
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 legenditemand look at the imagesource initialized at this point.
layerItem.ImageSource = layerItem.LegendItems.First().ImageSource; // set the image of the sublayer with the image of the first legenditem
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:
You might consider to use the legend control to get the symbols representing the sublayers. The legend control provides between 0 and many symbols for a sublayer (depending on the renderer). So the first question is 'which symbol do you want to associate to a sublayer?'If you decide to associate the first symbol and if you use a legend control in your application, you could initialize the sublayer symbol in the refreshed event: private void MyLegend_Refreshed(object sender, ESRI.ArcGIS.Client.Toolkit.Legend.RefreshedEventArgs e) { if (e.LayerItem.LayerItems != null) { foreach (var sublayerItem in e.LayerItem.LayerItems) { if (sublayerItem.LegendItems != null && sublayerItem.LegendItems.Any()) // if there is a legend item sublayerItem.ImageSource = sublayerItem.LegendItems.First().ImageSource; // set the image of the sublayer with the image of the first legenditem } } } Then you can display a listbox having its ItemsSource binded to a layer item of the legend ([0] = first map layer in this sample):<ListBox ItemsSource="{Binding LayerItems[0].LayerItems, ElementName=MyLegend}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Source="{Binding ImageSource}"/> <TextBlock Text="{Binding Label}" VerticalAlignment="Center" Margin="2,0"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>Likely there are many other ways to get this result, just my 2cts.
private void MyLegend_Refreshed(object sender, ESRI.ArcGIS.Client.Toolkit.Legend.RefreshedEventArgs e) { if (e.LayerItem.LayerItems != null) { foreach (var sublayerItem in e.LayerItem.LayerItems) { if (sublayerItem.LegendItems != null && sublayerItem.LegendItems.Any()) // if there is a legend item sublayerItem.ImageSource = sublayerItem.LegendItems.First().ImageSource; // set the image of the sublayer with the image of the first legenditem } } }
Yes, the API is backwards compatible. If there were any breaking change, they will be noted in this section of our SDK http://help.arcgis.com/en/webapi/silverlight/help/index.html#/What_s_new_in_2_1/016600000025000000/
Legend control is new with ArcGIS SL 2.1. Which version are you working with?
I dont have Legend control in ESRI.ArcGIS.Client.Toolkit
Signed in members can post, follow updates, and more. New here? Register a free account.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.