Skip to content

ProConcepts Parcel Fabric

uma2526 edited this page Jul 27, 2020 · 13 revisions

The parcel fabric is a comprehensive framework of functionality in ArcGIS for modeling parcels in organizations ranging from national cadastral agencies to local governments. This topic provides an introduction to the parcel fabric API. It details the classes and methods that query and edit the parcel fabric. The parcel fabric API is commonly used in conjunction with the geodatabase and editing.

Language:      C#
Subject:       Parcel Fabric
Contributor:   ArcGIS Pro SDK Team <arcgisprosdk@esri.com>
Organization:  Esri, http://www.esri.com
Date:          7/7/2020
ArcGIS Pro:    2.6
Visual Studio: 2017, 2019  

In this topic

Introduction

Overview

  • The parcel fabric API is a Data Manipulation Language (DML)-only API. This means that all schema creation and modification operations such as creating parcel types, enabling topology, adding and deleting rules, and so on, need to use the geoprocessing API.

  • Almost all of the methods in the parcel fabric API should be called on the Main CIM Thread (MCT). The API reference documentation on the methods that need to run on the MCT are specified as such. These method calls should be wrapped inside the QueuedTask.Run call. Failure to do so will result in ConstructedOnWrongThreadException being thrown. See Working with multi-threading in ArcGIS Pro to learn more.

  • In a multi-user environment, a parcel fabric is accessed via services and not client-server. As such the parcel fabric API is designed based on a services-only architecture. The parcel fabric also has a single use model that works directly on a file geodatabase. Implications of this architecture are described throughout this topic as appropriate.

Note: This topic assumes a basic understanding of the parcel fabric information model. See the online help for more information. See: What is the parcel fabric?

Namespaces and Extension Methods

The items of the parcel fabric are included in the ArcGIS.Desktop.Editing namespace. and in ArcGIS.Desktop.Mapping.

NOTE: For the ArcGIS Pro SDK 2.6 pre-release, parcel fabric objects and methods can be accessed using the internal namespace of the editing and mapping assemblies. This means that the add-ins that you create with the 2.6 pre-release will need to be re-compiled and re-deployed when the parcel fabric portion of the Pro SDK is released as a final product.

  • Add using ArcGIS.Desktop.Internal.Editing; and
  • Add using ArcGIS.Desktop.Internal.Mapping; to the top of your source files

Parcel data model

The parcel fabric is a controller dataset that handles a set of simple feature classes, a single geodatabase topology, and a set of parcel rules. Multiple parcel types can be added to a fabric. Each parcel type is represented by a polygon-polyline featureclass-pair. Each parcel type’s featureclass-pair has its own schema and can be extended with additional fields, domains and subtypes. Validating a parcel fabric’s topology rules and parcel rules may result in error features being created that report on rules that are outside their defined limits. To learn more, see the help topic Parcel fabric data model.

Parcel layer

Only one parcel layer can be added to a map view. Attempting to add a second parcel layer to a map view through the user interface or through code is prevented by the system, and an error is returned. Hence there can be a reliable expectation that there will only be one fabric layer in the map view. Consequently the following line of code is reliable for accessing the parcel layer.

var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();

The parcel layer represents the controller for all the corresponding layers for points, connections, records, and the parcel types.

You can test a layer to check if it is controlled by a fabric as follows:

// Check if a layer has a parcel fabric source
var myConnectionLinesLayer = MapView.Active.GetSelectedLayers().First();
bool bIsControlledByFabric = await myConnectionLinesLayer.IsControlledByParcelFabric(ParcelFabricType.ParcelFabric);

NOTE: In ArcGIS Pro the parcel fabrics from ArcMap are read-only. You can test if a layer's source is pointing to a parcel fabric created with the ArcMap-based schema by using the following code:

// Check if a layer has a source that is a parcel fabric for ArcMap 
var myLayer = MapView.Active.GetSelectedLayers().First();
bool bIsControlledByFabric = await myLayer.IsControlledByParcelFabric(ParcelFabricType.ParcelFabricForArcMap);

Parcel editing concepts

When editing a parcel fabric there are two high-level conceptual workflow modes:

  1. Record driven workflows
  2. Quality driven workflows

Record driven workflows and the Active Record

Record driven workflows are those that update the legal parcel information, and the parcel lineage; the parent parcel is retired when its child parcel(s) are created. This happens when entering data from a legal land record document such as a Deed, Subdivision Plan, Record of Survey, and so on. For example, an existing parcel gets subdivided into two portions. This subdivision occurs as a result of a legal document; we refer to that document as the legal record. The original parent parcel is retired by that record, and the two new parcels are created by that record. From the user workflow perspective, this requires that the first step is to create the record in the fabric and then to set that new record as active.

      await QueuedTask.Run( async () =>
      {
        Dictionary<string, object> RecordAttributes = new Dictionary<string, object>();

        string sNewRecord = "MyRecordName";
        var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();

        //if there is no fabric in the map then bail
        if (myParcelFabricLayer == null)
          return;
        var recordsLayer = await myParcelFabricLayer.GetParcelSubLayerAsync(ParcelSubLayerType.Records);

        var editOper = new EditOperation()
        {
          Name = "Create Parcel Fabric Record",
          ProgressMessage = "Create Parcel Fabric Record...",
          ShowModalMessageAfterFailure = true,
          SelectNewFeatures = false,
          SelectModifiedFeatures = false
        };

        RecordAttributes.Add("Name", sNewRecord);
        var editRowToken = editOper.CreateEx(recordsLayer, RecordAttributes);
        RowHandle rowHandle = new RowHandle(editRowToken);

        if (!editOper.Execute())
          return;

        Guid guid = rowHandle.GlobalID.Value;
        await myParcelFabricLayer.SetActiveRecordAsync(guid);

      });

The active record’s globally unique identifier (guid) is used to populate the fields called RetiredByRecord and CreatedByRecord. These fields are populated when new parcel features are created, or when existing parcels are retired and are being replaced by new parcels.

The concept of a record being "active" is client specific. The server does not persist any information related to a record being active. The client has a state, whereas the server is stateless.

var pRec = myParcelFabricLayer.GetActiveRecord();

When the active record is set, the edits that create new parcel features are tagged with this active record’s guid, and edits like Merge, Divide, Build will apply the correct parcel edits, and parcel lineage edits, such as in the above subdivide example.

await QueuedTask.Run( () =>
{
  // check for selected layer
  if (MapView.Active.GetSelectedLayers().Count == 0)
  {
    System.Windows.MessageBox.Show("Please select a feature layer in the table of contents", "Merge");
    return;
  }
  string sTargetParcelType = Microsoft.VisualBasic.Interaction.InputBox("Target Parcel Type:", "Merge To Parcel Type", "Tax");

  if (sTargetParcelType.Trim().Length == 0)
    return;

  //first get the feature layer that's selected in the table of contents
  var featSrcLyr= MapView.Active.GetSelectedLayers().OfType<FeatureLayer>().First();
  var featTargetLyr = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault(l => l.Name == sTargetParcelType);

  var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();
  var pRec = myParcelFabricLayer.GetActiveRecord();

  if (pRec == null)
  {
    System.Windows.MessageBox.Show("There is no Active Record. Please set the active record and try again.", "Merge Parcels");
    return;
  }
  if (featSrcLyr.SelectionCount == 0)
  {
    System.Windows.MessageBox.Show("There is no selection on the source layer.", "Merge Parcels");
    return;
  }
  var opMerge = new EditOperation()
  {
    Name = "Merge",
    ProgressMessage = "Merging parcels...",
    ShowModalMessageAfterFailure = true,
    SelectNewFeatures = true,
    SelectModifiedFeatures = false
  };
  opMerge.Merge(featTargetLyr, featSrcLyr, featSrcLyr.GetSelection().GetObjectIDs());
  opMerge.Execute();
  //When active record is set, and merging into the same parcel type, the original parcels are set historic with RetiredByRecord GUID field
  //When active record is set, the new merged parcel will be tagged with the Active record.
});

When the active record is not set, then the edits are standard edits, and from a parcel editing perspective are considered to be quality driven workflows.

// Check if there is an active record. If no active record then prompt user to set it or create it. 
// Otherwise, warn user that new features will not have an active record.
  var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();
  var pRec = myParcelFabricLayer.GetActiveRecord();

  if (pRec == null)
  {
    System.Windows.MessageBox.Show("There is no Active Record. Please set the active record and try again.", "Merge Parcels");
    return;
  }

Quality driven workflows

The quality driven workflows are used for things like attribute edits, such as correcting a parcel name, its stated area, or the attributed distance on a parcel’s boundary line. These quality driven workflows can also be geometry based such as re-aligning parcel boundaries. In general, quality driven workflows do not require an active record to be set and if an active record is set for the map, it will have no impact on the quality driven workflows.

Parcel types

The fabric has user-defined parcel types. Each parcel type is represented by a polygon feature class and a polyline feature class. A parcel type is created with a given name, such as 'Tax' or 'Lot', for example, and the parcel type is represented in the fabric as a polygon featureclass and polyline featureclass.

If polygons in a parcel type exist without lines, then you build the lines for the parcels. Similarly, if there are lines in a parcel type that form loops, but that do not enclose a parcel, then you can build parcel polygons from the parcel lines. The fabric also has points. The points are shared between parcel types, so a parcel’s points do not have a parcel type. Points are also tagged with a record when they are created.

In the map view a parcel type is a group layer containing a line and polygon feature layer. You can test a layer to check if it is controlled by a fabric as follows:

// Check if a layer has a parcel fabric source
var myParcelTypeLayer = MapView.Active.GetSelectedLayers().First();
bool bIsControlledByFabric = await myParcelTypeLayer.IsControlledByParcelFabric(ParcelFabricType.ParcelFabric);

What are parcel seeds?

Conceptually, seeds are the preliminary geometries for parcels. The seeds are used to help the user work with the parcel by maintaining the parcel's attributes in a compact geometry that is easy to move and place while in its un-built state. A seed is usually a small circular polygon geometry that is inside a closed loop of lines.

A seed is a row in the feature class table of a parcel type’s polygon feature class.

You can modify the attributes of the parcel seed, or move it to a different set of closed loop lines. During the build operation the geometry of the seed is modified to become a topologically complete parcel that fills the space enclosed by the parcel lines.

Order of operations

There is an order dependency for parcel data creation when using record driven workflows. In general there should be a record created for the edit, and then that record should be set active before creating parcel seeds, or before creating other parcel lines or points. Here is an example workflow:

  1. Create Record – this is making a new Record feature in the Records feature class, and setting it as the active record.
  2. Copy lines from an existing selection of non-fabric features into a parcel type called “Lot” in a parcel fabric. Parcel seeds are created automatically.
  3. Build the active record – this fills out the parcel type’s polygons, and creates fabric points at the shared nodes.
  4. Create another new record, and set it active.
  5. Copy lines from an existing selection of “Lot” parcels into a parcel type called “Tax” in the same parcel fabric. Parcel seeds are created automatically.
  6. Build the active record.

Extension methods

The fabric's parcel layer has extension methods to get and set the active record. Note that nearly all the methods in the parcel fabric API should be called on the Main CIM Thread (MCT). The API reference documentation on the methods that need to run on the MCT are indicated. These method calls should be wrapped inside the QueuedTask.Run call. Failure to do so will result in ConstructedOnWrongThreadException being thrown. See Working with multi-threading in ArcGIS Pro to learn more.

Get the Active Record

The current active record can be accessed as follows:

protected async override void OnClick()
{
  await QueuedTask.Run( () =>
  {
    var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();
    var theActiveRecord = myParcelFabricLayer.GetActiveRecord();
    if (theActiveRecord == null)
    {
      System.Windows.MessageBox.Show("There is no Active Record. Please set the active record and try again.",
               "Getting the Active Record");
      return;
    }
  });
}

Set the Active Record

A record with a given name can be found and set as the active record as follows:

await QueuedTask.Run( async () =>
{
  var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();
  //if there is no fabric in the map then bail
  if (myParcelFabricLayer == null)
    return;

  string sExistingRecord = "MyRecordName";
  if (!await myParcelFabricLayer.SetActiveRecordAsync(sExistingRecord))
  {
    MessageBox.Show("Record with that name not found.");
    myParcelFabricLayer.ClearActiveRecord();
    return;
  }
});

Creating a new Record

A new parcel fabric record can be created and set as the active record as follows:

await QueuedTask.Run( async () =>
{
  Dictionary<string, object> RecordAttributes = new Dictionary<string, object>();

  string sNewRecord = "MyRecordName");

  if (sNewRecord.Trim().Length == 0)
    return;

  var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();

  //if there is no fabric in the map then bail
  if (myParcelFabricLayer == null)
    return;
  var recordsLayer = await myParcelFabricLayer.GetParcelSubLayerAsync(ParcelSubLayerType.Records);

  var editOper = new EditOperation()
  {
    Name = "Create Parcel Fabric Record",
    ProgressMessage = "Create Parcel Fabric Record...",
    ShowModalMessageAfterFailure = true,
    SelectNewFeatures = false,
    SelectModifiedFeatures = false
  };

  RecordAttributes.Add("Name", sNewRecord);
  var editRowToken = editOper.CreateEx(recordsLayer, RecordAttributes);
  RowHandle rowHandle = new RowHandle(editRowToken);

  if (!editOper.Execute())
    return;

  Guid guid = rowHandle.GlobalID.Value;
  await myParcelFabricLayer.SetActiveRecordAsync(guid);

});

Integration with the editing API

Adding new features to a parcel type's polygon feature class, or to a parcel type's line feature class has specific behavior when a record is active. New parcel type features that are created will have the guid that is associated with the record stored in the parcel feature's CreatedByRecord field. Similarly, parcel point features and connection line features will have the active record guid assigned when they are created by the standard editing API. This is done automatically and does not require additional code. The code below does not proceed with the edit until the user has specified an active record. This ensures that the parcel fabric behavior is in effect. The code snippet below could be enhanced to prompt the user to create or choose a record, using code similar to that from the previous section, "Creating a new Record". A new parcel point can be added to a fabric as follows:

//make sure there is a fabric and an active record
var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();
if (myParcelFabricLayer == null)
  return;

var pRec = myParcelFabricLayer.GetActiveRecord();

if (pRec == null) //check if the user has specified the Active record 
{
  System.Windows.MessageBox.Show("There is no Active Record. Please set the active record and try again.",   
      "Add Test Point");
  return; //bail out here since the user needs to set the record that the point will have when created.
}

var pointLyr = layers.FirstOrDefault(l => l.Name == "Points" && l is FeatureLayer);
var editOper = new EditOperation()
{
  Name = "Create a test parcel point",
  ProgressMessage = "Create a test parcel point...",
  ShowModalMessageAfterFailure = true,
  SelectNewFeatures = true,
  SelectModifiedFeatures = false
};

Dictionary<string, object> PointAttributes = new Dictionary<string, object>();
var newPoint = MapView.Active.Extent.Center;
if (newPoint != null)
{
  PointAttributes.Add("Name", "MyTestPoint");
  PointAttributes.Add("IsFixed", 1);
  var editRowToken = editOper.CreateEx(pointLyr, newPoint, PointAttributes);

  editOper.Execute()
}

Other editing functions will also apply parcel behavior when an active record has been set. For example, the following code will merge selected features from a source layer into a target layer. This code is the same regardless of whether standard polygon features are being merged or if the features are a parcel type's polygon features. However, if the features are parcels, and the active record is set, then parcel fabric behavior is applied. This behavior is described after the following code block:

if (featLyrSource.SelectionCount == 0)
{
  System.Windows.MessageBox.Show("There is no selection on the source layer.", "Merge Parcels");
  return;
}

var opMerge = new EditOperation()
{
  Name = "Merge",
  ProgressMessage = "Merging parcels...",
  ShowModalMessageAfterFailure = true,
  SelectNewFeatures = true,
  SelectModifiedFeatures = false
};

opMerge.Merge(featLyrTarget, featLyrSource, featLyrSource.GetSelection().GetObjectIDs());
opMerge.Execute();

When the code above is executed on parcel polygon features and the source and target layers are different parcel types, and there is an active record, then the following attribute edits are applied automatically, without any additional code required:

  • the newly created merged parcel has its CreatedByRecordfield value updated with the active record's guid.
  • the newly created merged parcel has its StatedArea field value updated with the sum of the stated area values of the original selected parcels.

When the code above is executed on parcel polygon features and the source and target layers are the same parcel type, then parcel lineage is also captured with the following additional attribute edit:

  • the existing source parcels have their RetiredByRecordfield value updated with the active record's guid.

Creating new parcels

Parcels can be created in the fabric through code such as the approach in the example above for point creation. The parcel polygon feature and the parcel line features can be created directly in this way. The parcel fabric API also has additional methods for creating parcels. The following sections provide some code examples of these.

Copy standard line features into a parcel type

In addition to copying the source lines into the parcel type's line, the following code will also create parcel seeds within the detected closed-line loops:

editOper.CopyLineFeaturesToParcelType(srcStandardLineFeatureLayer, StandardLineObjectIds, 
              destParcelTypeLineLayer, destParcelTypePolygonLayer);
editOper.Execute();

The above code does not use a ParcelEditToken object; use of a token is optional. The code in the next section shows how a parcel edit token is used.

Copy a parcel's lines into a parcel type

In addition to copying the source parcel's lines into the target parcel type's line layer, the following code will also create parcel seeds at the centroid locations of the original source parcel polygons:

var ids = new List<long>(srcParcelTypePolygonFeatLyr.GetSelection().GetObjectIDs());

if (ids.Count == 0)
{
  System.Windows.MessageBox.Show("No selected parcels found. Please select parcels and try again.", 
     "Copy Parcel Lines To");
  return;
}

var kvp = new KeyValuePair<MapMember, List<long>>(srcParcelTypePolygonFeatLyr, ids);
var sourceParcelPolygonFeatures = new List<KeyValuePair<MapMember, List<long>>> { kvp };

ParcelEditToken peToken = editOper.CopyParcelLinesToParcelType(myParcelFabricLayer, sourceParcelPolygonFeatures, 
             destParcelTypeLineLayer, destParcelTypePolygonLayer, null, true, false, true);
var createdIDsSelectionSet = peToken.CreatedFeatures;
editOper.Execute();

Create parcel seeds for closed loops of parcel lines

var theActiveRecord = myParcelFabricLayer.GetActiveRecord();

if (theActiveRecord == null)
{
  System.Windows.MessageBox.Show("There is no Active Record. Please set the active record and try again.", "Create Parcel Seeds");
  return;
}

var guid = theActiveRecord.Guid;

var editOper = new EditOperation()
{
  Name = "Create Parcel Seeds",
  ProgressMessage = "Create Parcel Seeds...",
  ShowModalMessageAfterFailure = true,
  SelectNewFeatures = true,
  SelectModifiedFeatures = false
};

editOper.CreateParcelSeeds(myParcelFabricLayer, MapView.Active.Extent, guid);
editOper.Execute();

Build parcels from parcel seeds

protected async override void OnClick()
{
  await QueuedTask.Run( () =>
  {
    var myParcelFabricLayer = MapView.Active.Map.GetLayersAsFlattenedList().OfType<ParcelLayer>().FirstOrDefault();
    var theActiveRecord = myParcelFabricLayer.GetActiveRecord();
    var guid = theActiveRecord.Guid;

    if (myParcelFabricLayer == null)
      return;

    var editOper = new EditOperation()
    {
      Name = "Build Parcels",
      ProgressMessage = "Build Parcels...",
      ShowModalMessageAfterFailure = true,
      SelectNewFeatures = true,
      SelectModifiedFeatures = true
    };

    editOper.BuildParcelsByRecord(myParcelFabricLayer, guid);
    editOper.Execute();

  });
}

Duplicate parcels

You can duplicate parcels from multiple source types into a single target parcel type. The following code example uses just a single parcel type as a source in the List of KeyValuePair. Additional KeyValuePair items can be added to the List for duplicating from additional source parcel types.

var ids = new List<long>(sourceParcelTypePolygonLayer.GetSelection().GetObjectIDs());

if (ids.Count == 0)
{
  System.Windows.MessageBox.Show("No selected parcels found. Please select parcels and try again.", "Duplicate Parcels");
  return;
}

var kvp = new KeyValuePair<MapMember, List<long>>(sourceParcelTypePolygonLayer, ids);
var sourceFeatures = new List<KeyValuePair<MapMember, List<long>>> { kvp };

var theActiveRecord = myParcelFabricLayer.GetActiveRecord();

if (theActiveRecord == null)
{
  System.Windows.MessageBox.Show("There is no Active Record. Please set the active record and try again.", "Duplicate Parcels");
  return;
}

Guid guid=theActiveRecord.Guid;

var editOper  = new EditOperation()
{
  Name = "Duplicate Parcels",
  ProgressMessage = "Duplicate Parcels...",
  ShowModalMessageAfterFailure = true,
  SelectNewFeatures = true,
  SelectModifiedFeatures = false
};

editOper.DuplicateParcels(myParcelFabricLayer, sourceFeatures, guid, targetParcelTypePolygonLayer, -1);

editOper.Execute();

Updating parcels

Parcels can be directly updated in the fabric through code using the standard editing API. The parcel fabric API also has additional methods for updating existing parcels. The following sections and code snippets provide some examples of these.

Assign selected parcel features to the active record

var guid = theActiveRecord.Guid;
MapMember mapMemberSource = srcFeatLyr as MapMember;
var ids = new List<long>(srcFeatLyr.GetSelection().GetObjectIDs());
var kvp = new KeyValuePair<MapMember, List<long>>(mapMemberSource, ids);

var sourceFeatures = new List<KeyValuePair<MapMember, List<long>>> { kvp };
var editOper= new EditOperation()
{
  Name = "Assign Features to Record",
  ProgressMessage = "Assign Features to Record...",
  ShowModalMessageAfterFailure = true,
  SelectNewFeatures = true,
  SelectModifiedFeatures = false
};
editOper.AssignFeaturesToRecord(myParcelFabricLayer, sourceFeatures, guid, ParcelRecordAttribute.CreatedByRecord);
editOper.Execute();

History: setting parcels historic or current

var theActiveRecord = myParcelFabricLayer.GetActiveRecord();

if (theActiveRecord == null)
{
  System.Windows.MessageBox.Show("There is no Active Record. Please set the active record and try again.", "Copy Line Features To");
  return;
}

var ids = new List<long>(destPolygonL.GetSelection().GetObjectIDs()); 
//it is possible to do multiple layer selection. However this code uses a single layer

var kvp = new KeyValuePair<MapMember, List<long>>(destPolygonL, ids);
var sourceFeatures = new List<KeyValuePair<MapMember, List<long>>> { kvp };

Guid guid = theActiveRecord.Guid;

var editOper = new EditOperation()
{
  Name = "Set Parcels Historic",
  ProgressMessage = "Set Parcels Historic...",
  ShowModalMessageAfterFailure = true,
  SelectNewFeatures = true,
  SelectModifiedFeatures = false
};

editOper.UpdateParcelHistory(myParcelFabricLayer, sourceFeatures,guid,true);
editOper.Execute();

Change parcel types

MapMember mapMemberSource = sourceParcelPolygonFeatLayer as MapMember;
var ids = new List<long>(sourceParcelPolygonFeatLayer.GetSelection().GetObjectIDs());

var kvp = new KeyValuePair<MapMember, List<long>>(mapMemberSource, ids);
var sourceParcelPolygonFeatures = new List<KeyValuePair<MapMember, List<long>>> { kvp };

var opCpToPT = new EditOperation()
{
  Name = "Change Parcel Type",
  ProgressMessage = "Change Parcel Type...",
  ShowModalMessageAfterFailure = true,
  SelectNewFeatures = true,
  SelectModifiedFeatures = false
};

opCpToPT.ChangeParcelType(myParcelFabricLayer, sourceParcelPolygonFeatures, targetParcelPolygonFeatLyr, -1);
opCpToPT.Execute();

Deleting parcels

The standard delete method from the editing assembly is one valid approach for removing features from the parcel fabric. The DeleteParcels method does additional work that is specific to the parcel information model. Using this method, the parcels’ non-shared lines and points are also deleted.

var ids = new List<long>(theParcelTypePolygonFeatLyr.GetSelection().GetObjectIDs());
if (ids.Count == 0)
  return;

  var editOper = new EditOperation()
  {
    Name = "Delete Parcels",
    ProgressMessage = "Delete Parcels...",
    ShowModalMessageAfterFailure = true,
    SelectNewFeatures = false,
    SelectModifiedFeatures = false
  };

editOper.DeleteParcels(theParcelTypePolygonFeatLyr, ids);
editOper.Execute();

Developing with ArcGIS Pro

    Migration


Framework

    Add-ins

    Configurations

    Customization

    Styling


Arcade


Content


CoreHost


DataReviewer


Editing


Geodatabase

    3D Analyst Data

    Plugin Datasources

    Topology

    Object Model Diagram


Geometry

    Relational Operations


Geoprocessing


Knowledge Graph


Layouts

    Reports


Map Authoring

    3D Analyst

    CIM

    Graphics

    Scene

    Stream

    Voxel


Map Exploration

    Map Tools


Networks

    Network Diagrams


Parcel Fabric


Raster


Sharing


Tasks


Workflow Manager Classic


Workflow Manager


Reference

Clone this wiki locally