【ArcGIS Pro二次开发实例教程】(2):BSM字段赋值

一、简介

一般的数据库要素或表格都有一个BSM字段,用来标识唯一值。

此工具要实现的功能是:按一定的规律(前缀+中间的填充数字+OBJECT码)来给BSM赋值。

主要技术要点包括:

1、ProWindow的创建,Label,Combobox,Button控件的使用

2、获取当前内容框的所有要素图层

3、获取指定要素图层的所有字段

4、使用GP工具来进行【字段计算】


二、前端

1、ProWindo窗口的搭建

创建一个ArcGIS Pro模块加载项。​

在项目中,右键点击【项目】-【新建项】,添加1个【ArcGIS Pro ProWindow】,命名为【SetBSMCode.xaml】。

添加后会生成3个文件。

【SetBSMCode.xaml】是ProWindow的前端配置文件,用来搭建工具窗口。

【SetBSMCode.xaml.cs】是ProWindow的后端文件,用来处理各种后端事件。

【ShowSetBSMCode.cs】是一个Button按钮,点击后即可显示ProWindow窗口。

打开【SetBSMCode.xaml】,会发现其实就是一个WPF窗口。

关于ProWindow的基本操作方法可以看一下这个文章。

ProWindow的用法https://blog.csdn.net/xcc34452366/article/details/129552432这里介绍了几个常用控件的使用方法。我们这次用到的只有【Label、ComboBox、Button、TextBox】。

搭建窗口如下:

​然后为控件【cb_layer、cb_field、btn_go】设置一下事件,进行前后端的连接。

2、Config.daml设置

【Config.daml】的设置可以参照上一期教程,主要就是Button控件【ShowSetBSMCode.cs】的设置,这里就不再缀述:

注意Button图片要放在工程里,并将【生成操作】设置为【内容】。

点击调试,查看结果:


三、后端

打开【SetBSMCode.xaml.cs】,可以看到,已经有了3个空的事件方法。

1、【cb_layer_DropOpen】将当前地图中的所有要素图层添加到ComboBox中

首先清空ComboBox里的下拉项,避免之前操作的遗留。

通过map的【GetLayersAsFlattenedList()】方法获取当前地图中的所有要素图层,注意这部分代码要放在【QueuedTask.Run()】里面。

再把图层名逐个加入到ComboBox的下拉项。

这样当【cb_layer】下拉时,下拉框里就是显示所有的图层名。

cs 复制代码
private async void cb_layer_DropOpen(object sender, EventArgs e)
{
    // 先清空ComboBox里的下拉项,避免之前操作的遗留
    cb_layer.Items.Clear();
    // 获取当前地图
    Map map = MapView.Active.Map;
    // 获取所有要素图层
    List<FeatureLayer> featureLayers = await QueuedTask.Run(() =>
    {
        return map.GetLayersAsFlattenedList().OfType<FeatureLayer>().ToList();
    });
    // 把图层的名称以文本格式添加到ComboBox的下拉项
    foreach (FeatureLayer featureLayer in featureLayers)
    {
        cb_layer.Items.Add(featureLayer.Name);
    }
}

2、【cb_field_DropOpen】将上面选择图层的所有字段名添加到ComboBox中

首先要清空ComboBox里的下拉项,避免之前操作的遗留。

获取【cb_layer】中选定的图层名,并通过图层名来获取要素图层FeatureLayer要素。

最后再将要素图层的名称加入到ComboBox的下拉项。

同样要注意的是哪一部分代码在放在【QueuedTask.Run()】里面。

cs 复制代码
private async void cb_field_DropOpen(object sender, EventArgs e)
{
    // 获取cb_layer中选定的图层名
    string lyName = cb_field.Text;

    // 清空combox_field
    cb_field.Items.Clear();

    var fields = await QueuedTask.Run(() =>
    {
        // 获取当前地图
        Map map = MapView.Active.Map;

        // 通过图层名获取对应的要素图层FeatureLayer
        FeatureLayer featureLayer = map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault(l => l.Name == lyName);

        // 获取所选图层的所有字段
        return featureLayer.GetTable().GetDefinition().GetFields().ToList();
    });

    // 将所有字段名添加到combox_field中
    foreach (var field in fields)
    {
        cb_field.Items.Add(field.Name);
    }
}

3、【btn_go_Click】执行主程序

工具的核心代码放在这里。

一般这里的代码都比较长,也是问题频发区。我的习惯是直接在外面套一个【try...catch】用来捕捉错误。

cs 复制代码
try
{
    // TODO
}
catch (Exception ee)
{
    MessageBox.Show(ee.Message + ee.StackTrace);
    return;
}

具体流程如下:

先获取工具窗口里设置好的参数:图层名,字段名,前缀文字。

再获取图层的OID字段和BSM字段。

需要特别说明的是,这里只是一个简单的示例,先不考虑SHP数据的情况。

不过即使是GDB数据,它的OID字段也并不一定就是【objectID】,也可能是【objectID_1】等其它情况,所以这里需要重新查找,通过字段类型来确定OID字段。

获取到OID字段的名称和BSM字段的长度后,再使用GP工具来执行【计算字段】,得到最终结果。

有关GP工具的使用请查看这个文章:

GeoProcessing工具和自定义工具的调用https://blog.csdn.net/xcc34452366/article/details/129225381?spm=1001.2014.3001.5501执行完毕后,就关闭工具窗口,并弹出一个Message框,提示完成。

全代码如下:

cs 复制代码
private async void btn_go_Click(object sender, RoutedEventArgs e)
{
    try
    {
        // 图层名
        string layerName = cb_layer.Text;
        // 字段名
        string fieldName = cb_field.Text;
        // 前缀文字
        string front = txt_front.Text;

        await QueuedTask.Run(() =>
        {
            // 搜索OID字段和BSM字段
            Field OIDField = null;
            Field BSMField = null;
            // 获取当前地图
            Map map = MapView.Active.Map;
            // 通过图层名获取对应的要素图层FeatureLayer
            FeatureLayer featureLayer = map.GetLayersAsFlattenedList().OfType<FeatureLayer>().FirstOrDefault(l => l.Name == layerName);
            // 获取所选图层的所有字段
            var fields = featureLayer.GetTable().GetDefinition().GetFields().ToList();
            foreach (var field in fields)
            {
                // 通进OID字段的类型来搜索
                if (field.FieldType == FieldType.OID)
                {
                    OIDField = field;
                }
                // 通进BSM字段的名称来搜索
                if (field.Name == fieldName)
                {
                    BSMField = field;
                }
            }

            // 获取OID字段的名称和BSM字段的长度
            string OIDName = OIDField.Name;
            int BSMLength = BSMField.Length;

            // 计算字段的计算表达式
            string block = $"'{front}'+'0' * ({BSMLength} - len(str(!{OIDName}!+1))-{front.Length}) + str(!{OIDName}!)";

            // 生成计算字段工具所需的参数
            var par = Geoprocessing.MakeValueArray(layerName, fieldName, block);

            // 执行计算字段工具
            Geoprocessing.ExecuteToolAsync("management.CalculateField", par);

        });

        // 关闭窗口
        Close();
        // 弹出一个Message框,提示完成
        MessageBox.Show("BSM修改完成");

    }
    catch (Exception ee)
    {
        MessageBox.Show(ee.Message + ee.StackTrace);
        return;
    }
}

四、调试

点击调试,如图所示,选定【图层2】,字段选定【BSM】,前缀输入一个【350001】,点击【运行】

运行后打开图层属性表:

需要说明的是,这个工具只是个示例,有很多特殊情况还没有考虑进去,如SHP的OID字段值是从0开始而不是从1开始等。

作为一个初级教程,还是尽量先从简单的情况开始,优先考虑完成主要功能,在后面的教程中会慢慢深入。


五、工程文件下载

工程文件地址如下,在文件夹中找到【BSM字段赋值】下载即可。

【ArcGIS Pro二次开发实例教程】原代码合集https://pan.baidu.com/s/1HuS7engSHi1uK1sl70xtAQ?pwd=d6ji

相关推荐
杨超越luckly4 小时前
Python应用指南:高德交通态势数据
python·arcgis·数据挖掘·数据分析·交通态势
小彭努力中4 小时前
58.在 Vue 3 中使用 OpenLayers 绘制点、线、圆、多边形
前端·javascript·vue.js·arcgis·ecmascript·openlayers
鸿业远图科技6 小时前
安徽省乡镇界面图层+arcgis数据shp格式-乡镇名称和编码2020年+wgs84坐标内容测评
arcgis
m0_748235617 小时前
搭建Node.js后端
arcgis·node.js
yfs102415 小时前
ArcGis通过TIFF文件生成渔网
arcgis
鸿业远图科技15 小时前
安徽省地图arcgis数据美化后mxd文件shp格式下载后内容测评
arcgis
鸿业远图科技15 小时前
内蒙古水系详细很全shp格式arcgis软件无偏移坐标下载后内容测评
arcgis
鸿业远图科技2 天前
新疆乡镇界面图层arcgis格式shp数据有乡镇名称和编码2020年wgs84坐标无偏移数据内容测评
android·arcgis
规划GIS会2 天前
【ArcGIS Pro二次开发实例教程】(1):图层的前置、后置
arcgis·二次开发·arcgis pro