By Daniel Du
Have you ever run into such scenario that value of one field is computed from other fields? For example we can calculate the total land price from land price per unit and area. Most RDBMS can do this with stored procedure or similar, but for file based data source like SDF or SHP file, we have to do this ourselves by code. A good chance to do the calculation is when the modification on features are checked in, it would be better if Map 3D API provides an event like OnCheckIn, unfortunately, there is no such events in Geospatial Platform API.
But it can be done by a combination of serials events, they are FeatureInserted, FeatureUpdated, and FeatureDeleted of AcMapFeatureService.
Following code snippet domos how to use FeatureUpdated event, you can implement the other two to mimic OnCheckIn event is Map 3D. I blogged this topic a few years ago on my personal blog, if you prefer to read Chinese, please go to this link.
// (C) Copyright 2012 by Autodesk
//
using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.Gis.Map.Platform;
using OSGeo.MapGuide;
// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(MapOnCheckIn.MyCommands))]
namespace MapOnCheckIn
{
// This class is instantiated by AutoCAD for each document when
// a command is called by the user the first time in the context
// of a given document. In other words, non static data in this class
// is implicitly per-document!
public class MyCommands
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
//Following code sample demos how to mimic the OnCheckIn event
//when features are updated using fs.FeatureUpdated,
//You will need to implement FeatureDeleted and FeatureInserted yourself
[CommandMethod("AddFsEvents")]
public void AddFeatureServicesEvents()
{
AcMapFeatureService fs = AcMapServiceFactory.GetService(
MgServiceType.FeatureService) as AcMapFeatureService;
fs.FeatureUpdated += new FeatureUpdatedHandler(fs_FeatureUpdated);
AcMapMap currentMap = AcMapMap.GetCurrentMap();
currentMap.FeatureInstanceModified +=
new FeatureInstanceModifiedHandler(currentMap_FeatureInstanceModified);
}
// Triggered at once when the feature is updated, even it is not checked,
// This is not what we want.
void currentMap_FeatureInstanceModified(object sender,
FeatureInstanceModifiedEventArgs args)
{
ed.WriteMessage("FeatureInstanceModified fired!\n");
}
//Triggered when the feature is updated and checked in,
//This is the one we are looking for, it only triggered when checked in
//We can get the feature which is being checked in by Args.GetFeature()
//if more than one feature are updated, it will be fired more times
//so you can catch this even to handle each of them.
void fs_FeatureUpdated(object sender, AcMapFeatureEventArgs args)
{
ed.WriteMessage("FeatureUpdated fired! \n");
ed.WriteMessage("--------------------------------------\n");
ed.WriteMessage("PropertyName \t Value \n");
MgPropertyCollection props = args.GetFeature().GetProperties();
int propCount = props.Count;
for (int i = 0; i < propCount; i++)
{
string propName = props[i].Name;
string valueString;
switch (props[i].GetPropertyType())
{
case MgPropertyType.Int32:
valueString = (props[i] as MgInt32Property).GetValue().ToString();
break;
case MgPropertyType.String:
valueString = (props[i] as MgStringProperty).GetValue().ToString();
break;
default:
valueString = "<***>";
break;
}
ed.WriteMessage(propName + "\t" + valueString + "\n");
}
ed.WriteMessage("------------------------------------\n");
}
}
}
Hope this helps.