AnsweredAssumed Answered

Table of Contents for ArcGIS Runtime SDK for .NET v10.2.7

Question asked by AndrewFoster on Nov 1, 2016
Latest reply on Mar 5, 2019 by rscheitlin

We would like confirmation on our approach to building a Table of Contents in WPF using the ArcGIS Runtime SDK for .NET v10.2.7.  We have looked at the Legend control in the Toolkit but it does not seem to provide a way to manage the visibility of each sub-layer.

 

We have the following custom class which represents a map layer/sub-layer node displayed in a WPF TreeView control. We store the Layer Id in the Tag property.

public class TOCNodeClass : INotifyPropertyChanged

    {

        public string DisplayName { get; set; }

        public string Tag { get; set; }

        private bool isChecked;

        public bool IsChecked

        {

            get { return this.isChecked; }

            set

            {

                if (value != this.isChecked)

                {

                    this.isChecked = value;

                    NotifyPropertyChanged();

                }

            }

        }

        private bool isEnabled;

        public bool IsEnabled

        {

            get { return this.isEnabled; }

            set

            {

                if (value != this.isEnabled)

                {

                    this.isEnabled = value;

                    NotifyPropertyChanged();

                }

            }

        }

        public double MinScale { get; set; }

        public double MaxScale { get; set; }

        public ObservableCollection<TOCNodeClass> Nodes { get; set; }

 

        //PropertyChanged Handler

        public event PropertyChangedEventHandler PropertyChanged;

 

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")

        {

            if (PropertyChanged != null)

            {

                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }

        }

    }

 

We have an observable collection public ObservableCollection<TOCNodeClass> TOC { get; set; } to which we add a TOCNodeClass object for each map layer that is added to the MapView.Map.Layers collection.  Note each TOCNodeClass object has its own observable collection to allow adding sub-layers (feature layers).  We are building these objects using the properties found in each map layer’s AllLayersServiceInfo object and subsequently each sub-layer’s FeatureServiceLayerInfo object.

 

We have a WPF TreeView control bound to the TOC observable collection as shown below:

 

<TreeView x:Name="TableOfContents" Width="auto" HorizontalAlignment="Stretch" ItemsSource="{Binding TOC}">

<TreeView.ItemTemplate>

<HierarchicalDataTemplate DataType="{x:Type local:TOCNodeClass}"   ItemsSource="{Binding Nodes}">

<CheckBox x:Name="CheckBoxTOC" Tag="{Binding Tag}" IsEnabled="{Binding IsEnabled}" IsChecked="{Binding IsChecked}" Focusable="false" Checked="CheckBoxTOC_Checked" Unchecked="CheckBoxTOC_Unchecked">

<TextBlock Text="{Binding DisplayName}" FontWeight="Bold" MaxWidth="250" TextTrimming="CharacterEllipsis" />

</CheckBox>

</HierarchicalDataTemplate>

</TreeView.ItemTemplate>

 </TreeView>

 

Here's a list of methods we use to manage the state of the TreeView control:

public async void AddMapLayerToTOC(string strMapLayerId)

private bool AreAllMapLayerParentNodesChecked(TOCNodeClass objMapLayerNode, TOCNodeClass objChildNode)

private bool AreAllTOCParentNodesChecked(ObservableCollection<TOCNodeClass> objCollection, TOCNodeClass objChildNode)

private void CheckBoxTOC_Checked(object sender, RoutedEventArgs e)

private void CheckBoxTOC_Unchecked(object sender, RoutedEventArgs e)

private TOCNodeClass FindTOCNode(ObservableCollection<TOCNodeClass> objNodeCollection, string strTag)

private bool IsLayerEnabled(double dblMinScale, double dblMaxScale)

private void RefreshTOC()

public void RemoveMapLayerFromTOC(string strMapLayerId)

private void ToggleTOC(string strClickedLayerTag, bool blnIsChecked)

private void MapView_Main_NavigationCompleted(object sender, EventArgs e)

 

We found that we must manage each map layer’s ArcGISDynamicMapServiceLayer.VisibleLayers collection to show and hide the individual sub-layers (feature layers) by adding and removing the sub-layer’s Layer Id.  To complicate matters, each time a sub-layer’s checkbox changes state, we must inspect the checkbox state of all its parent nodes and all its sub-layer nodes to determine the visibility of each sub-layer.

 

We also have code in the MapView’s NavigationCompleted event to refresh the Table of Contents, as well as each map layer’s VisibleLayers collection, based on each sub-layer’s Min. Scale and Max. Scale settings.

 

Although we’ve made this work, it would be good to know if there's a better way to build a Table of Contents control.  Ultimately, we would like to display each sub-layer’s symbology in the Table of Contents; still trying to figure this out.

 

Thank you in advance for your suggestions.

Outcomes