Select to view content in your preferred language

Legend Group Labels

2034
9
06-03-2011 11:45 AM
karenvolarich
Occasional Contributor
I'm using the 2.1 API Legend.  I have several dozen map services within it and would like to organize them by topic (i.e. Weather, etc...).  They are in the order I want, but I would like to have a label act as a header at the beginning of a group within the legend.  Is it possible to add these labels?
0 Kudos
9 Replies
DominiqueBroux
Esri Frequent Contributor
You can hook up an handler to the legend event 'Refreshed' and reorganize the legend items in this handler.

The legend control uses a hierarchical data structure based on LayerItemViewModel class which can have children (LayerItems property), each child can have grand children and so on....

In the handler you can create new layeritems and insert then in the tree, or you can delete some of them, or you can move some of them  depending on your need.
0 Kudos
karenvolarich
Occasional Contributor
Do you have an example of some code for this?

I would be adding a group label like "Weather" and the adding 2 or 3 existing map services by their ID (e.g.:  ID="Nexrad", ID="NOAA", ID="NWS").

private string _weatherleg = "Weather";

if (e.LayerItem.Layer.ID == "Nexrad")
                MyLegend.LayerItems.Insert(2, _weatherleg);

where 2 is the index location of placing the text/label I'm inserting.  The problem is that I'm getting an error back stating that the LayerItemViewModel won't accept type string.

Thanks
0 Kudos
DominiqueBroux
Esri Frequent Contributor

private string _weatherleg = "Weather";

if (e.LayerItem.Layer.ID == "Nexrad")
MyLegend.LayerItems.Insert(2, _weatherleg);

where 2 is the index location of placing the text/label I'm inserting. The problem is that I'm getting an error back stating that the LayerItemViewModel won't accept type string.


You have to create a new LayerItemViewModel object because a string can't be directly inserted in the layeritems collection.

I created a sample for you (see attached result):

private void Legend_Refreshed(object sender, Legend.RefreshedEventArgs e)
{
if (e.LayerItem.Layer.ID != "dummy") // add here a test on the layers you want to group
{
    // Create group legend item if not existing
    var groupLayerItem = myLegend.LayerItems.Where(l => l.Label == "Group").FirstOrDefault();
    if (groupLayerItem == null)
    {
        groupLayerItem = new LayerItemViewModel(e.LayerItem.Layer) { Label = "Group", LayerItems = new System.Collections.ObjectModel.ObservableCollection<LayerItemViewModel>() };
         myLegend.LayerItems.Add(groupLayerItem);
    }
     // remove legend item from root and add it to the group item
    myLegend.LayerItems.Remove(e.LayerItem);
    groupLayerItem.LayerItems.Add(e.LayerItem);
 }
}


Note : While creating this simple, I noticed that there is no way to create a layer item without attaching it to a layer (the constructor without layer as argument is not public). So in the sample I arbitrarly attached the group layer to the first layer in that group. This has not too much sense and we will try to offer a better user story for grouping layers in a future version.
0 Kudos
karenvolarich
Occasional Contributor
So there are a few issues with the code:

1. It can't handle multiple groups -- it actually loads the same exact data each time in each group, despite breaking out the layerids.

1. The code

(e.LayerItem.Layer.ID != "dummy")

Why are you using != (does not equal) for the grouping?

I also think the following is an issue because it keeps trying to make it the first or default group:

var groupLayerItem = MyLegend.LayerItems.Where(l => l.Label == "Weather").FirstOrDefault();

So then it tries to make each group the first or default and loading everything into each group.
0 Kudos
karenvolarich
Occasional Contributor
So here is the code that finally worked for creating multiple groups (although I will say it doesn't like to add the first layer into any group -- not sure why):

if (e.LayerItem.Layer.ID == "NOAA Watches/Warnings" || e.LayerItem.Layer.ID == "Nexrad")
            {
                var groupLayerItem = MyLegend.LayerItems.Where(l => l.Label == "Weather").FirstOrDefault();
                if (groupLayerItem == null)
                {
                    groupLayerItem = new LayerItemViewModel(e.LayerItem.Layer)
                    {
                        Label = "Weather",
                        LayerItems =
                            new System.Collections.ObjectModel.ObservableCollection
                            <LayerItemViewModel>()
                    };
                    MyLegend.LayerItems.Add(groupLayerItem);

                }

                MyLegend.LayerItems.Remove(e.LayerItem);
                groupLayerItem.LayerItems.Add(e.LayerItem);

            }

if (e.LayerItem.Layer.ID == "LayerName" || e.LayerItem.Layer.ID == "AnotherLayerName" || e.LayerItem.Layer.ID == "ThirdLayerName)//List of all layer id that you want in the specific group
            {
                var groupLayerItem = MyLegend.LayerItems.Where(l => l.Label == "NewGroupName").FirstOrDefault();
                if (groupLayerItem == null)
                {
                    groupLayerItem = new LayerItemViewModel(e.LayerItem.Layer)
                    {
                        Label = "NewGroupName",
                        LayerItems =
                            new System.Collections.ObjectModel.ObservableCollection
                            <LayerItemViewModel>()
                    };
                    MyLegend.LayerItems.Add(groupLayerItem);

                }

                MyLegend.LayerItems.Remove(e.LayerItem);
                groupLayerItem.LayerItems.Add(e.LayerItem);

            }
0 Kudos
DominiqueBroux
Esri Frequent Contributor
(e.LayerItem.Layer.ID != "dummy")

Why are you using != (does not equal) for the grouping?


!= is just a sample working with a negative test excluding some layers from the group. You can obviously use a positive test on the layers to include (and I agree it's better).


I also think the following is an issue because it keeps trying to make it the first or default group:

var groupLayerItem = MyLegend.LayerItems.Where(l => l.Label == "Weather").FirstOrDefault();


I don't understand what you mean. It just a test to know if the group layer has already been created or not.


Anyway, it looks like you succeeded to get the result you were expecting. So 🙂


although I will say it doesn't like to add the first layer into any group -- not sure why


Strange, the initial sample I provided was adding the first layer in the group. What kind of layer is your first layer?
0 Kudos
karenvolarich
Occasional Contributor
!= is just a sample working with a negative test excluding some layers from the group. You can obviously use a positive test on the layers to include (and I agree it's better).



I don't understand what you mean. It just a test to know if the group layer has already been created or not.


Anyway, it looks like you succeeded to get the result you were expecting. So 🙂



Strange, the initial sample I provided was adding the first layer in the group. What kind of layer is your first layer?


It's a WMS, I'm thinking that might have something to do with it.  I moved it in my code to be the second layer and I'm still seeing the same issue -- so that makes me think it's the type.  The grouping worked fine when including Tile Service, Dynamic Service, and Feature Layer.

Also, because I'm using the tree view and not the flat view I'm getting a checkbox for the group label and I don't want one --- I want just the label for the group.  Any ideas?
0 Kudos
DominiqueBroux
Esri Frequent Contributor

Also, because I'm using the tree view and not the flat view I'm getting a checkbox for the group label and I don't want one --- I want just the label for the group. Any ideas?


The group layer is using the 'LayerTemplate'. I guess you can't remove the checkbox from this template if you want to be able to manage the sublayer visibilities?

There is only 3 templates defined at the legend control : LayerTemplate, MapLayerTemplate and LegendItemTemplate.

It looks like you would need a forth.

A workaround might be to set a template by legend item but it's not straightforward. Look at the beginning of this thread :
http://forums.arcgis.com/threads/31150-Selecting-different-templates-for-layers-in-legend-control
0 Kudos
karenvolarich
Occasional Contributor
That's what I was thinking...some kind of groupLayerTemplate construction that has no checkbox
0 Kudos