ArcGIS Pro SDK (七)编辑 4 行事件

Source

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();
        }
    }
}