ArcGIS Pro SDK (七)编辑 4 行事件
目录
环境:Visual Studio 2022 + .NET6 + ArcGIS Pro SDK 3.0
1 订阅行事件
protected void SubscribeRowEvent()
{
QueuedTask.Run(() =>
{
//监听图层的行事件
var featLayer = MapView.Active.GetSelectedLayers().First() as FeatureLayer;
var layerTable = featLayer.GetTable();
//订阅行事件
var rowCreateToken = RowCreatedEvent.Subscribe(OnRowCreated, layerTable);
var rowChangeToken = RowChangedEvent.Subscribe(OnRowChanged, layerTable);
var rowDeleteToken = RowDeletedEvent.Subscribe(OnRowDeleted, layerTable);
});
}
protected void OnRowCreated(RowChangedEventArgs args)
{
}
protected void OnRowChanged(RowChangedEventArgs args)
{
}
protected void OnRowDeleted(RowChangedEventArgs args)
{
}
2 在行事件中的映射中的单独表中创建记录
// 使用 RowChangedEventArgs 中的 EditOperation 来追加要执行的操作。
// 你的操作将成为操作的一部分,并合并到撤消堆栈中的一个项目中。
private void HookRowCreatedEvent()
{
// 订阅 RowCreatedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowCreatedEvent.Subscribe(MyRowCreatedEvent, table);
}
private void MyRowCreatedEvent(RowChangedEventArgs args)
{
// RowEvent 回调总是被 QueuedTask 调用,因此不需要
// 在 QueuedTask.Run lambda 中包装代码。
// 获取编辑操作
var parentEditOp = args.Operation;
// 设置一些属性
var attribs = new Dictionary<string, object> {
};
attribs.Add("Layer", "Parcels");
attribs.Add("Description", "OID: " + args.Row.GetObjectID().ToString() + " " + DateTime.Now.ToShortTimeString());
//在审计表中创建一条记录
var sTable = MapView.Active.Map.FindStandaloneTables("EditHistory").First();
var table = sTable.GetTable();
parentEditOp.Create(table, attribs);
}
3 在行事件中的单独表中创建记录
// 使用 RowChangedEventArgs 中的 EditOperation 来追加要执行的操作。
// 你的操作将成为操作的一部分,并合并到撤消堆栈中的一个项目中。
private void HookCreatedEvent()
{
// 订阅 RowCreatedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowCreatedEvent.Subscribe(OnRowCreatedEvent, table);
}
private void OnRowCreatedEvent(RowChangedEventArgs args)
{
// RowEvent 回调总是被 QueuedTask 调用,因此不需要
// 在 QueuedTask.Run lambda 中包装代码。
// 当创建行时更新不在映射中的单独表
// 必须使用 ArcGIS.Core.Data API 来编辑表。不要在 RowEvent 回调中使用新的编辑操作
try
{
// 获取编辑操作
var parentEditOp = args.Operation;
// 设置一些属性
var attribs = new Dictionary<string, object> {
};
attribs.Add("Description", "OID: " + args.Row.GetObjectID().ToString() + " " + DateTime.Now.ToShortTimeString());
// 使用新要素的信息更新 Notes 表
using (var geoDatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath))))
{
using (var table = geoDatabase.OpenDataset<Table>("Notes"))
{
parentEditOp.Create(table, attribs);
}
}
}
catch (Exception e)
{
MessageBox.Show($@"Error in OnRowCreated for OID: {
args.Row.GetObjectID()} : {
e.ToString()}");
}
}
4 修改行事件中的记录 - 使用 Row.Store
private void HookRowChangedEvent()
{
// 订阅 RowChangedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowChangedEvent.Subscribe(OnRowChangedEvent, table);
}
private Guid _currentRowChangedGuid = Guid.Empty;
protected void OnRowChangedEvent(RowChangedEventArgs args)
{
// RowEvent 回调总是被 QueuedTask 调用,因此不需要
// 在 QueuedTask.Run lambda 中包装代码。
var row = args.Row;
// 检查重入(仅在调用 row.Store 时)
if (_currentRowChangedGuid == args.Guid)
return;
var fldIdx = row.FindField("POLICE_DISTRICT");
if (fldIdx != -1)
{
// 验证对“police district”的任何更改
// 如果字段验证失败则取消编辑
if (row.HasValueChanged(fldIdx))
{
// 使用无效的区(5)取消编辑
var value = row["POLICE_DISTRICT"].ToString();
if (value == "5")
{
// 使用无效的“police district”值取消编辑
args.CancelEdit($"Police district {
row["POLICE_DISTRICT"]} is invalid");
}
}
// 更新描述字段
row["Description"] = "Row Changed";
// 这次更新会导致发生另一个 OnRowChanged 事件
// 跟踪行 guid 以避免递归
_currentRowChangedGuid = args.Guid;
row.Store();
_currentRowChangedGuid = Guid.Empty;
}
}
5 修改行事件中的记录 - 使用 EditOperation.Modify
private void HookChangedEvent()
{
// 订阅 RowChangedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowChangedEvent.Subscribe(MyRowChangedEvent, table);
}
private void MyRowChangedEvent(RowChangedEventArgs args)
{
// RowEvent 回调总是被 QueuedTask 调用,因此不需要
// 在 QueuedTask.Run lambda 中包装代码。
// 修改已创建行上的字段示例
var parentEditOp = args.Operation;
// 避免递归
if (_lastEdit != args.Guid)
{
// 在更改时更新字段
parentEditOp.Modify(args.Row, "ZONING", "New");
_lastEdit = args.Guid;
}
}
6 确定编辑时几何图形是否更改
private static FeatureLayer featureLayer;
private static void DetermineGeometryChange()
{
featureLayer = MapView.Active?.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault();
if (featureLayer == null)
return;
QueuedTask.Run(() =>
{
//监听行更改事件
ArcGIS.Desktop.Editing.Events.RowChangedEvent.Subscribe(OnRowChangedEvent2, featureLayer.GetTable());
});
}
private static void OnRowChangedEvent2(RowChangedEventArgs args)
{
// RowEvent 回调总是被 QueuedTask 调用,因此不需要
// 在 QueuedTask.Run lambda 中包装代码。
//获取图层的定义
var lyrDefn = featureLayer.GetFeatureClass().GetDefinition();
//获取要素类的形状字段
string shapeField = lyrDefn.GetShapeField();
//形状字段的索引
var shapeIndex = lyrDefn.FindField(shapeField);
//修改行的原始几何
var geomOrig = args.Row.GetOriginalValue(shapeIndex) as Geometry;
//修改行的新几何
var geomNew = args.Row[shapeIndex] as Geometry;
//比较两者
bool shapeChanged = geomOrig.IsEqual(geomNew);
}
7 取消删除
public static void StopADelete()
{
// 订阅适当表的 RowDeletedEvent
Table table = MapView.Active.Map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault().GetTable();
RowDeletedEvent.Subscribe(OnRowDeletedEvent, table);
}
private static void OnRowDeletedEvent(RowChangedEventArgs args)
{
// RowEvent 回调总是被 QueuedTask 调用,因此不需要
// 在 QueuedTask.Run lambda 中包装代码。
var row = args.Row;
// 如果要素位于 5 区,则取消删除
var fldIdx = row.FindField("POLICE_DISTRICT");
if (fldIdx != -1)
{
var value = row[fldIdx].ToString();
if (value == "5")
{
//带对话框取消
// 注意 - 无法取消托管和标准要素服务上的要素编辑。
args.CancelEdit("Delete Event\nAre you sure", true);
// 或不带对话框取消
// args.CancelEdit();
}
}
}