When will Quartz support GroupLayer and Geographic Transformations?

2058
12
Jump to solution
07-06-2017 07:23 AM
BjørnarSundsbø1
Occasional Contributor II

Looking at the missing features in the Quartz release, I'm wondering if you have a roadmap for this version you can share. We just completed migrating from the old Runtime for WPF before you released 100.1, and haven't looked too much into the quartz release.

We currently rely on GroupLayers for our show/hide functionality, though I expect we can circumvent that limitation on our own.

The other part I'm wondering about in Choosing the right version | ArcGIS for Developers  is Geographic Transformations; what do you mean by this? I see GeometryEngine.Project is available, but was wondering if you are referring to supporting multiple Spatial Reference in one map, automatic projection of graphics, or something else entirely.

0 Kudos
12 Replies
BjørnarSundsbø1
Occasional Contributor II

Ahh. Thank you for the response on that.

GroupLayer has been on my wishlist for a while. I suspect I can work around that need with with containers doing what I need related to showing/hiding groups, as well as modify opacity for a group of layers/overlays. When GroupLayer is reintroduced, will it be available for GraphicsOverlays, or only for background maps?

0 Kudos
dotMorten_esri
Esri Notable Contributor

Yeah there's a few ways you could do this yourself with a ViewModel. A group layer is really just visual grouping to the user - it doesn't really have any effect on the visual appearance on the actual map, so the trick is to "lie" about the layer hierarchy. And since the toolkit ToC control is centered around the ILayerContent interface, you can actually create a VM that works with that too. Below is an example that just groups all feature layers into a group-layer and puts all the basemap layers in its own single-item entry.

You can tweak this sample to group on something else. It could definitely be optimized here and there, but it's a good starting point for changing how a collection of layers gets exposed to the user.

    public class MapTocVM : IEnumerable<ILayerContent>, INotifyCollectionChanged
    {
        private Map _map;

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        public MapTocVM(Map map)
        {
            _map = scene;
            _map.OperationalLayers.CollectionChanged += OperationalLayers_CollectionChanged;
            _map.PropertyChanged += _map_PropertyChanged;
        }

        private void _map_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if(e.PropertyName == nameof(Map.Basemap))
                CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        private void OperationalLayers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        public IEnumerator<ILayerContent> GetEnumerator()
        {
            foreach(var layer in _map.OperationalLayers)
            {
                if(!(layer is FeatureLayer))
                    yield return layer;
            }
            yield return new GroupLayerContent(_map.OperationalLayers.OfType<FeatureLayer>(), "Feature Layers");
            yield return new BasemapLayerContent(_map.Basemap);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        private class GroupLayerContent : ILayerContent
        {
            IEnumerable<ILayerContent> _sublayers;
            public GroupLayerContent(IEnumerable<ILayerContent> sublayers, string name)
            {
                _sublayers = sublayers;
                Name = name;
            }

            public bool CanChangeVisibility => false;

            private bool m_isVisible;

            public bool IsVisible
            {
                get { return m_isVisible; }
                set { m_isVisible = value; }
            }

            public string Name { get; }

            public bool ShowInLegend { get; set; }

            public IReadOnlyList<ILayerContent> SublayerContents => new ReadOnlyCollection<ILayerContent>(_sublayers.ToList());

            public Task<IReadOnlyList<LegendInfo>> GetLegendInfosAsync() => Task.FromResult<IReadOnlyList<LegendInfo>>(null);

            public bool IsVisibleAtScale(double scale) => true;
        }

        private class BasemapLayerContent : ILayerContent
        {
            private Basemap _basemap;

            public BasemapLayerContent(Basemap basemap)
            {
                _basemap = basemap;
            }

            public bool CanChangeVisibility => false;

            public bool IsVisible { get => true; set => throw new NotSupportedException(); }

            public string Name => "Basemap: " + _basemap.Name;

            public bool ShowInLegend { get => true; set => throw new NotImplementedException(); }

            public IReadOnlyList<ILayerContent> SublayerContents => null;

            public Task<IReadOnlyList<LegendInfo>> GetLegendInfosAsync() => Task.FromResult<IReadOnlyList<LegendInfo>>(null);

            public bool IsVisibleAtScale(double scale) => true;
        }
    }
BjørnarSundsbø1
Occasional Contributor II

That's excellent!

I'll see what I need to do to adapt this to do the same for Graphic overlays, but I suppose the principle should be the same, and hopefully there shouldn't be much trouble to bind the adaptation to a TreeView in some form or other, or just create a wrapper class implementing the interface.

0 Kudos