Select to view content in your preferred language

How to get selected feature(s) from selection tool?

822
6
Jump to solution
10-11-2022 03:35 AM
OscarYam
Occasional Contributor

I would like to create a button that updates the selected feature's attribute. When I started coding, I found that I cannot get the selected feature after I use the default selection tool(the tools under esri_mapping_selectToolPalette). Is it any method to get the selected feature from the default selection tool?

0 Kudos
1 Solution

Accepted Solutions
CharlesMacleod
Esri Regular Contributor

Subscribe to the MapSelectionChangedEvent. Any changes to the map selection via selection tool, via custom selection, etc. will fire the event.

ArcGIS.Desktop.Mapping.Events.MapSelectionChangedEvent.Subscribe((args) => {
   //If u are only interested in one particular map...
   if (args.Map.Name == "The Map Name I am Interested In") {
     System.Diagnostics.Debug.WriteLine("Selection changed");
     var sel = args.Selection;//This is what is selected
     if (sel.Count == 0) {
       System.Diagnostics.Debug.WriteLine(" 0 features selected");
       return;
     }
     //enumerate current selection - a series of keyvalue pairs
     //key is the MapMember, Value is the list of OIDs
     foreach(var kvp in sel.ToDictionary()) {
  
       var oids = kvp.Value; //OIDs of the selected features
       var oid_str_list = oids.Select(oid => oid.ToString()).ToList();
       var oid_str = string.Join(",", oid_str_list);
       System.Diagnostics.Debug.WriteLine(
                     $"{kvp.Key.Name}: {oid_str}");

       if (kvp.Key is BasicFeatureLayer fl) {
         //TODO selection is on a vector layer...
       }
       else if (kvp.Key is StandaloneTable tbl) {
         //TODO selection is on a table...
       }
       //else if (....)
       //{
       //   etc,etc.
       //}
    }
   }
 });

 

Note: In 2.x, the event argument syntax is slightly different. The Selection property is a Dictionary so there is no sel.ToDictionary() as such.

View solution in original post

6 Replies
CharlesMacleod
Esri Regular Contributor

Subscribe to the MapSelectionChangedEvent. Any changes to the map selection via selection tool, via custom selection, etc. will fire the event.

ArcGIS.Desktop.Mapping.Events.MapSelectionChangedEvent.Subscribe((args) => {
   //If u are only interested in one particular map...
   if (args.Map.Name == "The Map Name I am Interested In") {
     System.Diagnostics.Debug.WriteLine("Selection changed");
     var sel = args.Selection;//This is what is selected
     if (sel.Count == 0) {
       System.Diagnostics.Debug.WriteLine(" 0 features selected");
       return;
     }
     //enumerate current selection - a series of keyvalue pairs
     //key is the MapMember, Value is the list of OIDs
     foreach(var kvp in sel.ToDictionary()) {
  
       var oids = kvp.Value; //OIDs of the selected features
       var oid_str_list = oids.Select(oid => oid.ToString()).ToList();
       var oid_str = string.Join(",", oid_str_list);
       System.Diagnostics.Debug.WriteLine(
                     $"{kvp.Key.Name}: {oid_str}");

       if (kvp.Key is BasicFeatureLayer fl) {
         //TODO selection is on a vector layer...
       }
       else if (kvp.Key is StandaloneTable tbl) {
         //TODO selection is on a table...
       }
       //else if (....)
       //{
       //   etc,etc.
       //}
    }
   }
 });

 

Note: In 2.x, the event argument syntax is slightly different. The Selection property is a Dictionary so there is no sel.ToDictionary() as such.

OscarYam
Occasional Contributor

Would you mind explaining more about where should these codes go to? Should those codes go to Module1.cs or the button.cs? I am using Arcgis pro 3.0.

0 Kudos
CharlesMacleod
Esri Regular Contributor

The Module is probably the best place. There is an initialize method in the Module which is probably a good spot. I would also set your module autoLoad attribute to true in the Config.daml.

 <modules>
    <insertModule id="...." className="Module1" autoLoad="true"
       caption="Module1">
internal class Module1 : Module {

  private static Module1 _this = null;
  ...
  protected override bool Initialize()
  {
  	//TODO subscribe to the mapping event here

  	return true;
  }

 

 

0 Kudos
OscarYam
Occasional Contributor

Thank you for your solution. Here is what I come up with to fit my situation.

I added the following code in module1.cs like you said. And created a class to store selections so I can access the selected features within my addin project.

protected override bool Initialize()
{
	SubscribleMapSelectionChangedEvent();
	return base.Initialize();
}

private void SubscribleMapSelectionChangedEvent()
{
	ArcGIS.Desktop.Mapping.Events.MapSelectionChangedEvent.Subscribe((args) => {
		//If u are only interested in one particular map...
		if (args.Map.Name == "My map")
		{
			#if DEBUG
			System.Diagnostics.Debug.WriteLine("Selection changed");
			#endif
			var sel = args.Selection;//This is what is selected
			if (sel.Count == 0)
			{
				#if DEBUG
				System.Diagnostics.Debug.WriteLine(" 0 features selected");
				#endif
				return;
			}
			else
			{
				CommonObject.GlobalVariables.SelectedFeatures = sel.ToDictionary();
			}
		}
	});
}

 

0 Kudos
CharlesMacleod
Esri Regular Contributor

Nice work Oscar. One thing I thought I would mention: The module class is actually already global throughout the addin (by design). All classes can access it via the special "singleton" property called "Current".

Therefore, if you wanted, you could add a "SelectedFeatures" property to your module class directly and access it that way. So it could look something like this:

internal class Module1 : Module  {
    ...
    private Dictionary<MapMember, List<long>> _selFeatures;

    //Any (non-private) module property or method can be accessed from 
    //anywhere within the addin
    internal Dictionary<MapMember, List<long>> SelectedFeatures => 
     _selFeatures ??= new Dictionary<MapMember, List<long>>();

    //elsewhere...access the property via Module1.Current...
    foreach(var kvp in Module1.Current.SelectedFeatures) {

 

0 Kudos
OscarYam
Occasional Contributor

Thanks for your additional info, cheers!

0 Kudos