Select to view content in your preferred language

Keeping layer checkbox in sync with layer visibility - SL3 to SL4 issue

959
5
09-29-2010 10:10 AM
MatthewCarey
Regular Contributor
I have an application that reuses the code from ESRI's 'SubLayer List' sample to populate a listbox with checkboxes to turn each sublayer of the map service on and off (also known as a TOC).

After certain events I turn on a sublayer programmatically. In the Silverlight 3 version of my app I used a method called UpdateLayerList (which I believe was part of an earlier ESRI sample) that would repopulate the listbox and made sure that the checkboxes reflected the visible/not visible status of the sublayers.

In translating the app to Silverlight 4 and looking at the latest sample, the UpdateLayerList method apparently became unnecessary, and now if I try to make use of it the list box becomes blank.

I can still turn on a sublayer programmatically with no issues, but cannot figure out a way to either refresh the TOC with the checkboxes reflecting the sublayers' actual visibility, or at least say specifically "turn on this checkbox for this layer."

I believe the binding process may be part of the answer or there's something else that I'm missing, so any help would be greatly appreciated! Thanks.
0 Kudos
5 Replies
JenniferNery
Esri Regular Contributor
One way of achieving this is to create your own class MyLayerInfo with additional property IsVisible, using an ObservableCollection of this type as ItemsSource for your listbox, and adding a method that updates IsVisible property by checking dynamic layer's VisibleLayers.

Xaml-code:  (update ListBox)
 <ListBox x:Name="SubLayerListBox" Margin="0,5,0,0"  
                         Grid.Row="1">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <CheckBox Margin="2"
                                  Name="DynamicLayerCalifornia"
                                  Content="{Binding LayerInfo.Name}" 
                                  IsChecked="{Binding IsVisible}" 
                                  Tag="{Binding LayerInfo.ID}"
                                  ClickMode="Press" 
                                  Click="CheckBox_Click" />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

Code-behind: (update ListBox' ItemsSource)
        ObservableCollection<MyLayerInfo> MySubLayers = new ObservableCollection<MyLayerInfo>();
        public SubLayerList()
        {
            InitializeComponent();
            this.SubLayerListBox.ItemsSource = MySubLayers;
        }

        private void ArcGISDynamicMapServiceLayer_Initialized(object sender, EventArgs e)
        {
            ESRI.ArcGIS.Client.ArcGISDynamicMapServiceLayer dynamicServiceLayer =
                sender as ESRI.ArcGIS.Client.ArcGISDynamicMapServiceLayer;
   foreach (LayerInfo l in dynamicServiceLayer.Layers)
    MySubLayers.Add(new MyLayerInfo(l));
            if (dynamicServiceLayer.VisibleLayers == null)
                dynamicServiceLayer.VisibleLayers = GetDefaultVisibleLayers(dynamicServiceLayer);
 UpdateIsVisibleProperty(dynamicServiceLayer.VisibleLayers.ToList());
        }

//TODO: call this method everytime dynamicServiceLayer.VisibleLayers is updated
        private void UpdateIsVisibleProperty(List<int> visibleLayerList)
        {
            foreach (MyLayerInfo info in MySubLayers)
                info.IsVisible = visibleLayerList.Contains(info.LayerInfo.ID);
        }


 public class MyLayerInfo : INotifyPropertyChanged
 {
  public MyLayerInfo(LayerInfo info)
  {
   LayerInfo = info;
  }
  private LayerInfo layerInfo;
  public LayerInfo LayerInfo
  {
   get { return layerInfo; }
   set
   {
    if (layerInfo != value)
    {
     layerInfo = value;
     if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs("LayerInfo"));
    }
   }
  }
  bool isVisible;
  public bool  IsVisible
  {
   get { return isVisible; }
   set
   {
    if (isVisible != value)
    {
     isVisible = value;
     if (PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs("IsVisible"));
    }
   }
  }
  public event PropertyChangedEventHandler PropertyChanged;
 }
0 Kudos
MatthewCarey
Regular Contributor
This solution worked fine for me - thanks a lot for your help!
0 Kudos
AnastasiaAourik
Emerging Contributor
I would like to generate a list box that shows the layers in mulitiple map services.
Plus, I will only include the layers that do not have the word 'label' in the layername.

The sample and binding you have shown works well for a single map service.

Can anyone help with buiding this for mulitiple map services...

I have started by creating a class AllWellsLayerInfo : INotifyPropertyChanged

and have attributes
LayerInfo, and isVisible
that fires a propertychangedEvent on those 2 fields, respectively.

Can someone direct me to a solution...
0 Kudos
RobertBrodsky
Deactivated User
Hi;
Try using this.

ScrollViewer see example below

<userControls:WindowPanel x:Name="LayersPanel"
   IsOpen="{Binding ElementName=btnToggleLayerList, Path=IsChecked, Mode=TwoWay}"
      HorizontalAlignment="Right" VerticalAlignment="Top" Width="233" Height="393"
   Margin="0,68,6,0">

            <ScrollViewer Width="207" Height="355" Padding="0">
                <ListBox ItemsSource="{Binding ElementName=Map, Path=Layers.[XXXXX].Layers}"
                         x:Name="SubLayerListBox">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <CheckBox Margin="2"
                                  Name="XXX Layers"
                                  Content="{Binding Name}"
                                  IsChecked="{Binding DefaultVisibility, Mode=TwoWay}"
                                  Tag="{Binding ID}"
                                  ClickMode="Press"
                                  Click="LayersCheckBox_Click"
                                  />
                    </DataTemplate>
                </ListBox.ItemTemplate>
                </ListBox>
            </ScrollViewer>

            <userControls:WindowPanel.ContentTitle>
                <StackPanel Orientation="Horizontal">
                    <Image Source="Images/Layers-32.png"
                           HorizontalAlignment="Left" VerticalAlignment="Top" Stretch="Fill"
                           Width="20" Height="20" Margin="5,2,0,0" />
                    <TextBlock Foreground="White" FontSize="12"
                               Text="PERA Layers" Width="100" TextWrapping="NoWrap" Height="Auto"
                               HorizontalAlignment="Left" Margin="5,3,0,0" />
                </StackPanel>
            </userControls:WindowPanel.ContentTitle>
        </userControls:WindowPanel>
0 Kudos
JenniferNery
Esri Regular Contributor
To use with multiple map services, you can subscribe to the same ArcGISDynamicMapServiceLayer_Initialized event in Post#2. And modify it so that you can exclude sublayers that contains 'label' in their name.

foreach (LayerInfo l in dynamicServiceLayer.Layers)
{
 if(!l.Name.Contains("label)")
  MySubLayers.Add(new MyLayerInfo(l));
}
0 Kudos