一、简介
一般的数据库要素或表格都有一个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