Select to view content in your preferred language

Snapping.SetLayerSnapModes to edit snapping rules for multiple layers

936
3
Jump to solution
11-17-2022 02:56 PM
RichardOxales
Occasional Contributor

I'm currently trying to create a tool and need to be able to manipulate the snapping settings on individual layers so that the snapping environment only snaps to a desired set of feature layers. I was using the SetSnappable method on FeatureLayer originally but the operation is slow for the number of layers I need to manipulate (200+ layers on a map takes over 10 seconds to run flayer.SetSnappable(true) on all of them).

I'm attempting to use Snapping.SetLayerModes(SetLayerSnapModes(IDictionary<Layer,LayerSnapModes>,Boolean) but unfortunately, anything I enter in here seems to get ignored and I haven't been able to get something similar to the  current code snippet working.

The outcome I expect is that the layers I feed become the only layers the user can snap to, but in practice, it seems that the global Snapping environment's options I set (point, edge, end, vertex) take priority and all layers in the map can still be snapped to, even if I specify in the dictionary object that all snap modes for certain layers should be false.

Am I doing something wrong here? It seems because the layers still appear with snapping enabled in the Snap window and I've selected certain things to snap to (point, vertex, etc.), the options I set don't matter, but it sounds like LayerSnapModes are supposed to let me set different snapping rules from those. Do I have the wrong idea, or am I writing this incorrectly possibly

Here was my attempt:

public static void UpdateMapSnapping(List<FeatureLayer> layersToSnap)
{
    Snapping.IsEnabled = true

    // Reset snap settings to the options I want
    Snapping.SetSnapMode();
    Snapping.SetSnapMode(SnapMode.Point, true);
    Snapping.SetSnapMode(SnapMode.Edge, true);
    Snapping.SetSnapMode(SnapMode.End, true);
    Snapping.SetSnapMode(SnapMode.Vertex, true)

    var mapLayers = MapView.Active.map.GetLayersAsFlattenedList().OfType<FeatureLayer>().ToList();
    var snapModes = new Dictionary<Layer, LayerSnapModes>();

    foreach (var flayer in mapLayers)
    {
        // This was done previously; all layers appear as snappable in the Snap table of contents
        // flayer.SetSnappable(true);
        if layersToSnap.Contains(flayer)
        {
            // Want to snap to this layer
            snapModes.Add(flayer, new LayerSnapModes(true));
        }
        else
        {
            // Do not want to snap to this layer
            snapModes.Add(flayer, new LayerSnapModes(false));
        }
    }

    // Set all layers to either snap or not snap
    // Setting the boolean to true or false doesn't appear to change anything, all layers are still snappable.
    Snapping.SetLayerSnapModes(snapModes, false);
}

 

0 Kudos
1 Solution

Accepted Solutions
RichardOxales
Occasional Contributor

After playing around with this a bit more, I think I figured out what the issue was. My map had group layers containing the layers I was trying to manipulate and it seems like I needed to also adjust the snap settings on those in order to get the child layers to work properly. It wasn't enough to adjust only Feature Layers.

All of my map layers now have their snapping correctly turning on/off and it executes pretty much instantly, so no 10 second wait.

Here's the code I settled on:

 

Dictionary<Layer, LayerSnapModes> mapLSMs = Snapping.GetLayerSnapModes(MapView.Active.Map);

foreach (var item in mapLSMs)
{
    var layer = item.Key;
    if (!snapLayers.Contains(layer))
    {
        mapLSMs[layer].Vertex = false;
        mapLSMs[layer].Point = false;
    }
    else
    {
        mapLSMs[layer].Vertex = true;
        mapLSMs[layer].Point = true;
        var parentLayer = layer.Parent as Layer;
        while (parentLayer != null)
        {
            // Loop up through the snap layer's parents and enable any of those parent layers on the way up.
            mapLSMs[parentLayer].Vertex = true;
            mapLSMs[parentLayer].Point = true;
            parentLayer = parentLayer.Parent as Layer;
        }
    }
}

Snapping.SetLayerSnapModes(mapLSMs, true);

 

 

View solution in original post

0 Kudos
3 Replies
GKmieliauskas
Esri Regular Contributor

Hi,

Look at the OverlayExamples sample from Esri community samples. ConfigureSnappingAsync method demonstrates how to setup snapping.

0 Kudos
RichardOxales
Occasional Contributor

Hi @GKmieliauskas,

Thanks for the response. The sample is quite similar to using FeatureLayer.SetSnappable(bool isSnappable) and unfortunately, I'm seeing the same slowness issue there. The tool becomes mostly unusable if the user needs to wait an additional 20 seconds just to set up the snapping settings on layers between actions. Snapping.SetLayerModes() with a dictionary seems to do what I want, but I can't get it to work.

For additional context, this is working off a Utility Network dataset with connections. I see that the standard Create tool automatically adjusts snapping to override with the UN connectivity rules based on which attributes the user set for the feature being placed and I'm trying to do something similar to this.

0 Kudos
RichardOxales
Occasional Contributor

After playing around with this a bit more, I think I figured out what the issue was. My map had group layers containing the layers I was trying to manipulate and it seems like I needed to also adjust the snap settings on those in order to get the child layers to work properly. It wasn't enough to adjust only Feature Layers.

All of my map layers now have their snapping correctly turning on/off and it executes pretty much instantly, so no 10 second wait.

Here's the code I settled on:

 

Dictionary<Layer, LayerSnapModes> mapLSMs = Snapping.GetLayerSnapModes(MapView.Active.Map);

foreach (var item in mapLSMs)
{
    var layer = item.Key;
    if (!snapLayers.Contains(layer))
    {
        mapLSMs[layer].Vertex = false;
        mapLSMs[layer].Point = false;
    }
    else
    {
        mapLSMs[layer].Vertex = true;
        mapLSMs[layer].Point = true;
        var parentLayer = layer.Parent as Layer;
        while (parentLayer != null)
        {
            // Loop up through the snap layer's parents and enable any of those parent layers on the way up.
            mapLSMs[parentLayer].Vertex = true;
            mapLSMs[parentLayer].Point = true;
            parentLayer = parentLayer.Parent as Layer;
        }
    }
}

Snapping.SetLayerSnapModes(mapLSMs, true);

 

 

0 Kudos