ProGuide Templates - kataya/arcgis-pro-sdk GitHub Wiki
Language: C#
Subject: Map Exploration
Contributor: ArcGIS Pro SDK Team <[email protected]>
Organization: Esri, http://www.esri.com
Date: 11/24/2020
ArcGIS Pro: 2.7
Visual Studio: 2017, 2019
Templates are a central concept in the editing environment in ArcGIS Pro. The Editor relies on the use of templates for creating features in feature layers or rows in standalone tables.
This ProGuide demonstrates how to create, modify and use templates. The code used to illustrate this guide can be found at the EditingTemplates Sample.
Prerequisites
- Download and install the sample data required for this guide as instructed in ArcGIS Pro SDK Community Samples Releases.
- Create a new ArcGIS Pro Module Add-in, and name the project EditingTemplates. If you are not familiar with the ArcGIS Pro SDK, you can follow the steps in the ProGuide Build your first add-in to get started.
Step 1
Add a new ArcGIS Pro Add-ins | ArcGIS Pro Button to the project and name the item CreateTemplateWithCIM. Modify the Config.daml button item as follows:
- Change the caption to "Create Template with CIM"
- Change the tooltip heading to "Create Template With CIM" and the tooltip text to "Creates a new template using the CIM"
Add another new ArcGIS Pro Add-ins | ArcGIS Pro Button to the project and name this item CreateTemplateWithExt. Modify the config.daml for this button item as follows:
- Change the caption to "Create Template with Extension"
- Change the tooltip heading to "Create Template With Extension" and the tooltip text to "Creates a new template using the extension method"
The config.daml should look like the following
<button id="EditingTemplates_CreateTemplateWithCIM" caption="Create Template With CIM"
className="CreateTemplateWithCIM" loadOnClick="true"
smallImage="Images\GenericButtonBlue16.png" largeImage="Images\GenericButtonBlue32.png">
<tooltip heading="Create Template With CIM">Creates a new template using the CIM<disabledText /></tooltip>
</button>
<button id="EditingTemplates_CreateTemplateWithExt" caption="Create Template with Extension"
className="CreateTemplateWithExt" loadOnClick="true"
smallImage="Images\GenericButtonBlue16.png" largeImage="Images\GenericButtonBlue32.png">
<tooltip heading="Create Template with Extension">Creates a new template using the extension method<disabledText /></tooltip>
</button>
Build the sample. Debug the add-in and start ArcGIS Pro. Open the 'Interacting with Maps' project from the Community Samples Data you previously downloaded. Validate the UI on the ArcGIS Pro ribbon.
Close ArcGIS Pro and return to Visual Studio.
Step 2
The Pro API provides access to many of the common objects and methods used within the ArcGIS Pro application. However there are many more objects and properties available via the Cartographic Information Model (CIM); a specification used to persist and transfer cartographic descriptions of GIS datasets such as maps, layers, layouts, symbols and layout elements. The CIM model is represented in XML or JSON and exposed via the ArcGIS.Core.CIM namespace. Here is a list of all the CIM classes. You can use any of these CIM classes to expand upon the managed API.
The pattern for accessing a CIM object is to use the managed_object.GetDefinition method. If you wish to modify a CIM object, use both the managed_object.GetDefinition and managed_object.SetDefinition methods as a pair. The following is a typical coding pattern for updating the CIM definition of a managed object:
await QueuedTask.Run(() =>
{
managed_object.GetDefinition();
set properties, do other things ....
managed_object.SetDefinition();
});
In many cases it is often useful to know the xml format of a CIM object to ensure you populate the object correctly. You can use the CIM Viewer utility to inspect many CIM models within Pro. You can also access the xml yourself by using the CIMObject.ToXml() method in test code within your add-in.
Two of the CIM objects we will use in this guide are the CIMFeatureLayer and CIMFeatureTemplate objects. Here is a sample of the xml structure of a CIMFeatureTemplate object.
<CIMFeatureTemplate xsi:type="typens:CIMFeatureTemplate">
<Description>Template for Polygon 1</Description>
<Name>Polygon 1</Name>
<Tags>Polygon</Tags>
<ToolProgID>8f79967b-66a0-4a1c-b884-f44bc7e26921</ToolProgID>
<DefaultValues xsi:type="typens:PropertySet">
<PropertyArray xsi:type="typens:ArrayOfPropertySetProperty">
<PropertySetProperty xsi:type="typens:PropertySetProperty">
<Key>notetype</Key>
<Value xsi:type="xs:short">1</Value>
</PropertySetProperty>
</PropertyArray>
</DefaultValues>
</CIMFeatureTemplate>
This example of a CIMFeatureTemplate has a name, description, tags, a progID (actually a GUID) and a set of default values defined as a KeyValuePair. We will be creating an object similar to this.
Open the CreateTemplateWithCIM.cs file. Replace the existing empty OnClick method with the following.
protected override async void OnClick()
{
MapView mapvView = MapView.Active;
if (mapvView == null)
return;
// get the Fire Stations layer
FeatureLayer layer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Fire Stations");
if (layer == null)
return;
await QueuedTask.Run(() =>
{
//remove existing templates and regenerate from the renderer
layer.AutoGenerateTemplates(true);
//get the CIM layer definition
var layerDef = layer.GetDefinition() as CIMFeatureLayer;
//set new template values
var myTemplateDef = new CIMFeatureTemplate();
myTemplateDef.Name = "My template";
myTemplateDef.Description = "some description";
myTemplateDef.WriteTags(new[] { "Point", "TesterTag" });
// set some default attributes
myTemplateDef.DefaultValues = new Dictionary<string, object>();
myTemplateDef.DefaultValues.Add("City", "Portland");
// set the default construction tool
myTemplateDef.SetDefaultToolDamlID("esri_editing_SketchPointTool");
// remove construction tools from being available with this template
List<string> filter = new List<string>();
// guid = esri_editing_ConstructPointsAlongLineCommand
filter.Add("BCCF295A-9C64-4ADC-903E-62D827C10EF7");
myTemplateDef.ToolFilter = filter.ToArray();
//get all templates on this layer
// NOTE - layerDef.FeatureTemplates could be null
// if Create Features window hasn't been opened
var layerTemplates = layerDef.FeatureTemplates?.ToList();
if (layerTemplates == null)
layerTemplates = new List<CIMEditingTemplate>();
//add the new template to the layer template list
layerTemplates.Add(myTemplateDef);
//update the layerdefinition with the templates
layerDef.FeatureTemplates = layerTemplates.ToArray();
// check the AutoGenerateFeatureTemplates flag,
// set to false so our changes will stick
if (layerDef.AutoGenerateFeatureTemplates)
layerDef.AutoGenerateFeatureTemplates = false;
//and commit
polygonLayer.SetDefinition(layerDef);
});
}
This subroutine follows the standard CIM pattern of using the GetDefinition method to obtain the CIM layer definition from a feature layer, performs a number of actions to change the CIM defintion (creating a new CIMFeatureTemplate object and assigning properties), and finishes by calling the SetDefinition method to commit the CIM changes to the feature layer.
The changes to the CIM consist of creating a new CIMFeatureTemplate object and assigning name, description, tags and default values. The template's default tool is set using the SetDefaultToolDamlID helper method to assign a daml-id. (Note: The xml sample of a CIMFeatureTemplate above shows the ToolProgID property does not use daml-ids; the construction tool is represented internally using a GUID. This GUID is also a property of a construction tool and can be found in the Editing.daml file. We use the SetDefaultToolDamlID helper method to assign the easier to recognize daml-ids.) Use the ToolFilter property to remove construction tools from being available with the template. No helper method currently exists for the ToolFilter so this property requires the tool's to be removed be defined using their raw GUID rather than a daml-id. (If this was illustrated in our xml sample, we would see the ToolFilter property populated with GUID strings.)
Once the template is defined, add it to the template collection from the layer definition. It's necessary to check for a null collection as the template definitions may not exist until the Create Features window has been opened due to loading optimizations. Don't forget to assign the updated template collection back to the layer definition.
Finally, it is also VERY important to check the AutoGenerateFeatureTemplates property on the layer definition. This indicates whether feature templates are automatically generated by the system. If you are coding modifications to the templates via the CIM, you need to ensure the AutoGenerateFeatureTemplates flag is set to false to ensure your changes are not overwritten by the auto generation logic. If this flag is false, then the layer templates have been customized and are persisted and auto generation logic is not run.
Build the sample and fix any compile errors. Debug the add-in and start ArcGIS Pro. Open the 'Interacting with Maps' project. Ensure the Fire Stations layer is visible and open the Create Features window (the button is available from the Edit tab). Navigate to the Add-In tab and click the Create Template with CIM button. A new template is created in the Create Features window. Verify the properties of the template by right clicking on the template and choosing Properties and checking the General, Tools and Attributes pages.
Close ArcGIS Pro and return to Visual Studio.
Step 3
Open the CreateTemplateWithExt.cs file. We will create a similar template on the same layer using the CreateTemplate extension method. Replace the existing empty OnClick method with the following.
protected override async void OnClick()
{
MapView mapvView = MapView.Active;
if (mapvView == null)
return;
// get the Fire Stations layer
FeatureLayer layer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Fire Stations");
if (layer == null)
return;
await QueuedTask.Run(() =>
{
//remove existing templates and regenerate from the renderer
layer.AutoGenerateTemplates(true);
// load the schema
var insp = new Inspector();
insp.LoadSchema(layer);
// set some default attributes
insp["City"] = "Portland";
// set up tags
var tags = new[] { "Point", "tag2" };
// default construction tool - use daml-id
string defaultTool = "esri_editing_SketchPointTool";
// filter - use daml-id
List<string> filter = new List<string>();
filter.Add("esri_editing_ConstructPointsAlongLineCommand");
// create a new CIM template - new extension method
var newTemplate = layer.CreateTemplate("My extension template",
"sample description", insp, defaultTool,
tags, filter.ToArray());
});
}
In this example, use the Inspector object to set default attributes. The default construction tool and tool filters can be specified using daml-ids. Call the CreateTemplate extension method which interacts with the CIM internally and sets the AutoGenerateFeatureTemplates flag appropriately. As you would expect, the extension method hides a lot of the detail required when using the CIM.
Build the sample and fix any compile errors. Debug the add-in and start ArcGIS Pro. Open the 'Interacting with Maps' project. Ensure the Fire Stations layer is visible and open the Create Features window. Navigate to the Add-In tab and click the Create Template with Extension button. A new template is created in the Create Features window. Verify the properties of the template.
Close ArcGIS Pro and return to Visual Studio.
Step 4
In addition to creating templates, you may wish to modify an existing template. This requires using the CIM pattern shown in Step 2.
Add a new ArcGIS Pro Add-ins | ArcGIS Pro Button to the project and name the item ModifyTemplateCIM. Modify the Config.daml button item as follows:
- Change the caption to "Modify Template with CIM"
- Change the tooltip heading to "Modify Template With CIM" and the tooltip text to "Modify a template using the CIM"
<button id="EditingTemplates_ModifyTemplateCIM" caption="Modify Template with CIM"
className="ModifyTemplateCIM" loadOnClick="true"
smallImage="Images\GenericButtonBlue16.png" largeImage="Images\GenericButtonBlue32.png">
<tooltip heading="Modify Template with CIM">Modify a template using the CIM<disabledText /></tooltip>
</button>
Open the ModifyTemplateCIM.cs file and paste the following into the OnClick method.
protected override async void OnClick()
{
MapView mapvView = MapView.Active;
if (mapvView == null)
return;
// get the layer
FeatureLayer layer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Portland Precincts");
if (layer == null)
return;
await QueuedTask.Run(() =>
{
//remove existing templates and regenerate from the renderer
layer.AutoGenerateTemplates(true);
// get the template
var template = layer.GetTemplate("North Precinct");
if (template != null)
{
// get the definition
var templateDef = template.GetDefinition() as CIMFeatureTemplate;
// change the default tool
templateDef.SetDefaultToolDamlID("esri_editing_SketchRightPolygonTool");
// commit the definition
template.SetDefinition(templateDef);
}
});
}
This button again illustrates the GetDefintion, SetDefinition pattern of accessing the CIM; however this time we access the CIMFeatureTemplate class from an EditingTemplate object; retrieved using the GetTemplate API method from the FeatureLayer. As before, use the SetDefaultToolDamlID extension method to alter the default construction tool for the template. You can also modify other attributes of the template by using the properties on the CIMFeatureTemplate object.
Debug and start ArcGIS Pro opening the previous project. Click the Modify Template with CIM button. Activate the North Precinct template in the Create Features pane; notice the new default construction tool is the Right Angle Polygon Tool.
Close ArcGIS Pro and return to Visual Studio.
Step 5
Even though templates are defined with default attribute values, you can use templates at run time and temporarily override these default values. The following example will show you how to activate a template and override it's default attribute values to store three features with different values.
Add a new ArcGIS Pro Add-ins | ArcGIS Pro Button to the project and name the item CreateFeatures. Modify the Config.daml button item as follows:
- Change the caption to "Create Features with Template"
- Change the tooltip heading to "Create Features with Template" and the tooltip text to "Create Features with Template"
<button id="EditingTemplates_CreateFeatures" caption="Create Features with Template"
className="CreateFeatures" loadOnClick="true"
smallImage="Images\GenericButtonBlue16.png" largeImage="Images\GenericButtonBlue32.png">
<tooltip heading="Create Features with Template">Create Features with Template<disabledText /></tooltip>
</button>
Open the CreateFeatures.cs file and paste the following into the OnClick method.
protected override async void OnClick()
{
MapView mapvView = MapView.Active;
if (mapvView == null)
return;
// get the Fire Stations layer
FeatureLayer layer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Fire Stations");
if (layer == null)
return;
await QueuedTask.Run(async () =>
{
// use the center of the mapextent as the geometry
var extent = mapvView.Extent;
var geometry = extent.Center;
// set up 2 other geometries offset
var geometry2 = GeometryEngine.Instance.Move(geometry, extent.Width / 4, extent.Height / 4);
var geometry3 = GeometryEngine.Instance.Move(geometry, -extent.Width / 4, -extent.Height / 4);
// get one of the templates
var template = layer.GetTemplate("Fire Stations");
if (template != null)
{
// activate the template - use the default tool
await template.ActivateDefaultToolAsync();
// you can also activate a template via a specific tool
// (assuming tool is available for the template)
// await template.ActivateToolAsync("esri_editing_SketchPointTool");
// perform the creation
var op = new EditOperation();
op.Name = "Create feature";
// use template default field values
op.Create(template, geometry);
// modify default template properties
var insp = template.Inspector;
insp["City"] = "xxx";
// create with the modified fields and a different geometry
op.Create(template, geometry2);
// reset the modified fields back to original defaults
insp.Cancel();
// change the field again
insp["City"] = "yyy";
// create with the modified fields and a different geometry
op.Create(template, geometry3);
// reset the modified fields back to original defaults
insp.Cancel();
// execute the operation
bool result = op.Execute();
}
});
}
Retrieve a template by name from a layer using the GetTemplate method. Activate it by using the ActivateDefaultToolAsync or ActivateToolAsync methods. Then use the template's Inspector to set field values. A template's Inspector object is only available and non-null after the template has been activated. In this example we create 3 features with 3 different City values by overriding the template default attributes, wrapping the feature creation in an EditOperation.
Debug and start ArcGIS Pro, opening the previous project. Click the Create Features with Template button. Three features will be created. Open the Attributes pane and verify the City attribute for each of the new features.
Close ArcGIS Pro and return to Visual Studio.
Step 6
Group templates allow you to create and place many features across multiple layers in one editing action. They are created by choosing an existing feature template as the primary template and adding other templates as component templates to create additional features based on the geometry or location of the primary feature. For example, in the Portland project, you can create a new precinct and configure the component templates to automatically create a fire station and police station at predefined locations relative to that precinct.
Here is the xml of the group template we will create in this guide.
<CIMGroupEditingTemplate xsi:type="typens:CIMGroupEditingTemplate">
<Description>some desc</Description>
<Name>My Group Template</Name>
<Tags>Group; Polygon</Tags>
<ToolProgID>8f79967b-66a0-4a1c-b884-f44bc7e26921</ToolProgID>
<ToolFilter xsi:type="typens:ArrayOfString">
<String>0a7c16b9-1cfd-467f-8ece-6ba376192431</String>
<String>7a61439f-21e3-50a9-1f9e-54545d8f53e4</String>
<String>acd53634-cbc7-44d5-bde9-692fa8d45850</String>
</ToolFilter>
<BaseName>North Precinct</BaseName>
<BasePart xsi:type="typens:CIMGroupEditingTemplatePart">
<LayerURI>CIMPATH=portland_crimes/portland_pd_precincts.xml</LayerURI>
<Name>North Precinct</Name>
<TransformationID>esri_editing_transformation_polygonPrimaryIdentity</TransformationID>
</BasePart>
<Parts xsi:type="typens:ArrayOfCIMGroupEditingTemplatePart">
<CIMGroupEditingTemplatePart xsi:type="typens:CIMGroupEditingTemplatePart">
<LayerURI>CIMPATH=portland_2d/fire_stations.xml</LayerURI>
<Name>Fire Stations</Name>
<TransformationID>esri_editing_transformation_pointAtPolygonCentroid</TransformationID>
</CIMGroupEditingTemplatePart>
<CIMGroupEditingTemplatePart xsi:type="typens:CIMGroupEditingTemplatePart">
<LayerURI>CIMPATH=portland_2d/police_stations.xml</LayerURI>
<Name>Police Stations</Name>
<TransformationID>esri_editing_transformation_pointAtPolygonStart</TransformationID>
</CIMGroupEditingTemplatePart>
</Parts>
</CIMGroupEditingTemplate>
The CIMGroupEditingTemplate object is very similar to a CIMFeatureTemplate in that it has a name, description, tags, default tool and a filtered toolset. It also has properties which define the primary template and the component templates. The primary template is defined using the BaseName and BasePart properties using a CIMGroupEditingTemplatePart object. The component templates are part of the Parts array, each defined using a CIMGroupEditingTemplatePart. In this example, the base template is the 'North Precinct' template followed by 2 parts; a Fire Station template which will create a feature at the centroid of the precinct polygon and a Police Station template which will create a feature at the start point of the precinct polygon.
As you've already seen, a CIM object is typically made up of integers, doubles and strings. This means that items such as tool identifiers, and in this case transformation IDs, are not easily discoverable when looking at the objects documentation. This is why we recommend using the CIM viewer or viewing the xml of an existing object to obtain specific information. For this particular object, you can also determine all the available transformation ID strings provided by the Editing module by opening the Editing.daml file and searching for the esri_editing_TemplateGroup_BuilderMethods
category.
To programmatically create this group template add a new ArcGIS Pro Add-ins | ArcGIS Pro Button to the project and name the item CreateGroupTemplateWithCIM. Modify the Config.daml button item as follows:
- Change the caption to "Create Group Template with CIM"
- Change the tooltip heading to "Create Group Template With CIM" and the tooltip text to "Creates a new Group Template using the CIM"
<button id="EditingTemplates_CreateGroupTemplateWithCIM" caption="Create Group Template With CIM"
className="CreateGroupTemplateWithCIM" loadOnClick="true"
smallImage="Images\GenericButtonBlue16.png" largeImage="Images\GenericButtonBlue32.png">
<tooltip heading="Create Group Template With CIM">
Creates a new Group Template using the CIM<disabledText /></tooltip>
</button>
Open the CreateGroupTemplateWithCIM.cs file and paste the following into the OnClick method.
protected override async void OnClick()
{
MapView mapvView = MapView.Active;
if (mapvView == null)
return;
// get the layers
FeatureLayer precinctLayer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Portland Precincts");
FeatureLayer fireLayer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Fire Stations");
FeatureLayer policeLayer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Police Stations");
if ((precinctLayer == null) || (fireLayer == null) || (policeLayer == null))
return;
await QueuedTask.Run(() =>
{
//remove existing templates and regenerate from the renderer
precinctLayer.AutoGenerateTemplates(true);
fireLayer.AutoGenerateTemplates(true);
policeLayer.AutoGenerateTemplates(true);
// get the templates that will make up the group template
var precinctTemplate = precinctLayer.GetTemplate("North Precinct");
var fireTemplate = fireLayer.GetTemplates().FirstOrDefault();
var policeTemplate = policeLayer.GetTemplates().FirstOrDefault();
if ((precinctTemplate == null) || (fireTemplate == null) || (policeLayer == null))
return;
// group templates are stored on the primary layer
var layerDef = precinctLayer.GetDefinition() as CIMFeatureLayer;
//set new template values
var myGroupTemplateDef = new CIMGroupEditingTemplate();
myGroupTemplateDef.Name = "My Group Template";
myGroupTemplateDef.Description = "some desc";
myGroupTemplateDef.WriteTags(new[] { "Group", "Polygon"});
// set the default construction tool
myGroupTemplateDef.SetDefaultToolDamlID("esri_editing_SketchPolygonTool");
// remove construction tools from being available with this template
List<string> filter = new List<string>();
// guid = esri_editing_SketchFreehandPolygonTool
filter.Add("0A7C16B9-1CFD-467f-8ECE-6BA376192431");
// esri_editing_SketchAutoCompleteFreehandPolygonTool
filter.Add("ACD53634-CBC7-44d5-BDE9-692FA8D45850");
// esri_editing_SketchTracePolygonTool
filter.Add("E22F7D98-007D-427C-8282-13704F7C84C3");
myGroupTemplateDef.ToolFilter = filter.ToArray();
// create the base part
var basepart = new CIMGroupEditingTemplatePart();
basepart.LayerURI = precinctLayer.URI;
basepart.Name = precinctTemplate.Name;
basepart.TransformationID = "esri_editing_transformation_polygonPrimaryIdentity";
// assign the base part to the groupTemplate
myGroupTemplateDef.BaseName = basepart.Name;
myGroupTemplateDef.BasePart = basepart;
// create the component parts
var part = new CIMGroupEditingTemplatePart();
part.LayerURI = fireLayer.URI;
part.Name = fireTemplate.Name;
part.TransformationID = "esri_editing_transformation_pointAtPolygonCentroid";
var part2 = new CIMGroupEditingTemplatePart();
part2.LayerURI = policeLayer.URI;
part2.Name = policeTemplate.Name;
part2.TransformationID = "esri_editing_transformation_pointAtPolygonStart";
// build the list of component templates
List<CIMGroupEditingTemplatePart> parts = new List<CIMGroupEditingTemplatePart>();
parts.Add(part);
parts.Add(part2);
// assign to the group template
myGroupTemplateDef.Parts = parts.ToArray();
//get all templates on this layer
// NOTE - layerDef.FeatureTemplates could be null
// if Create Features window hasn't been opened
var layerTemplates = layerDef.FeatureTemplates?.ToList();
if (layerTemplates == null)
layerTemplates = new List<CIMEditingTemplate>();
//add the new template to the layer template list
layerTemplates.Add(myGroupTemplateDef);
//update the layerdefinition with the templates
layerDef.FeatureTemplates = layerTemplates.ToArray();
// check the AutoGenerateFeatureTemplates flag,
// set to false so our changes will stick
if (layerDef.AutoGenerateFeatureTemplates)
layerDef.AutoGenerateFeatureTemplates = false;
//and commit
precinctLayer.SetDefinition(layerDef);
});
}
Start by retrieving the relevant layers from the active MapView. Then retrieve the necessary templates that the group template is to be based on. Create a new CIMGroupEditingTemplate
object and assign the name, description, default construction tool and tool filter. The primary part of the group template is defined using a CIMGroupEditingTemplatePart
; specify the layer, template and appropriate transformation ID. The component templates are also defined using a CIMGroupEditingTemplatePart
with the appropriate layer, template and transformation ID. Once created, assign these component templates to the group template. Finally add the group template to the FeatureTemplates collection on the layer definition and assign the entire layer definition back to the layer.
Debug and start ArcGIS Pro opening the previous project. Click the Create Group Template with CIM button. A new group template will be added to the Create Features window.
Close ArcGIS Pro and return to Visual Studio.
STEP 7
Open the CreateGroupTemplateWithExt.cs file. We will create a similar group template as the previous example using extension methods.
Replace the existing empty OnClick method with the following.
protected override async void OnClick()
{
MapView mapvView = MapView.Active;
if (mapvView == null)
return;
// get the layers
FeatureLayer precinctLayer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Portland Precincts");
FeatureLayer fireLayer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Fire Stations");
FeatureLayer policeLayer = mapvView.Map.GetLayersAsFlattenedList().
OfType<FeatureLayer>().FirstOrDefault(l => l.Name == "Police Stations");
if ((precinctLayer == null) || (fireLayer == null) || (policeLayer == null))
return;
await QueuedTask.Run(() =>
{
// group templates are stored on the primary layer
var layerDef = precinctLayer.GetDefinition() as CIMFeatureLayer;
// create group template from primary layer
var myGroupTemplateDef = precinctLayer.CreateGroupTemplateDefinition("My Group Template", "North Precinct", "some desc", new[] { "Group", "Polygon" });
// set the default construction tool
myGroupTemplateDef.SetDefaultToolDamlID("esri_editing_SketchPolygonTool");
// remove construction tools from being available with this template
List<string> filter = new List<string>();
// guid = esri_editing_SketchFreehandPolygonTool
filter.Add("0A7C16B9-1CFD-467f-8ECE-6BA376192431");
// esri_editing_SketchAutoCompleteFreehandPolygonTool
filter.Add("ACD53634-CBC7-44d5-BDE9-692FA8D45850");
// esri_editing_SketchTracePolygonTool
filter.Add("E22F7D98-007D-427C-8282-13704F7C84C3");
myGroupTemplateDef.ToolFilter = filter.ToArray();
// add component parts
myGroupTemplateDef = myGroupTemplateDef.AddComponentTemplate(fireLayer, "Fire Stations", GroupTemplateBuilderMethods.builderPointAtPolygonCentroid);
myGroupTemplateDef = myGroupTemplateDef.AddComponentTemplate(policeLayer, "Police Stations", GroupTemplateBuilderMethods.builderPointAtPolygonStart);
// add group template to layer
var template = precinctLayer.CreateTemplate(myGroupTemplateDef);
});
}