ArcGIS Runtime SDK for .NET (查询功能实现)
1、界面设计
<MenuItem Header="查询" Height="30" Width="100" Background="CadetBlue" BorderBrush="Aqua" BorderThickness="1">
<MenuItem Header="简单查询" Height="30" BorderBrush="Khaki" BorderThickness="2" Click="easyQuery"/>
<MenuItem Header="点击查询" Height="30" BorderBrush="Khaki" BorderThickness="2" Click="MenuSelectFeat_Click"/>
<MenuItem Header="Identity查询" Height="30" BorderBrush="Khaki" BorderThickness="2" Click="MenuIdentify_Click"/>
</MenuItem>
2、C#代码实现
简单查询
private async Task QueryStateFeature3(FeatureLayer _featureLayer, string sQueryFieldName, string stateName)
{
try
{ // 定义 一个查询参数对象
QueryParameters pQueryP = new QueryParameters();
string sformat = stateName.Trim().ToUpper(); // 去掉地名两边的空格,并转为大写
// 设置查询条件
pQueryP.WhereClause = "upper(" + sQueryFieldName + ") LIKE '%" + sformat + "%'"; // where语句,将字段名转成大写
// 依据查询参数,进行要素选择操作
//Esri.ArcGISRuntime.Mapping.SelectionMode.Add 将要选择的要素附加到当前选定要素列表中。
//Esri.ArcGISRuntime.Mapping.SelectionMode.New 将当前选定要素列表替换为要选定的要素。
//Esri.ArcGISRuntime.Mapping.SelectionMode.Subtract 从当前选定要素列表中删除要素。
//_featureLayer.SelectFeaturesAsync(查询表达式,查询模式)
await _featureLayer.SelectFeaturesAsync(pQueryP, Esri.ArcGISRuntime.Mapping.SelectionMode.New); // 等待其查询完毕
//提取已选择的要素
//_featureLayer.GetSelectedFeaturesAsync() 表示异步获取选定功能操作的任务对象。任务结果的值是FeatureQueryResult对象;仅显示选定的功能。
FeatureQueryResult pQueryResult = await _featureLayer.GetSelectedFeaturesAsync();
// 存到列表中
List<Feature> pListFeatures = pQueryResult.ToList();
//使用空间引用和空几何体初始化EnveloperBuilder类的新实例。
EnvelopeBuilder pEnvBuilder = new EnvelopeBuilder(MyMapView.Map.SpatialReference);
for (int i = 0; i < pListFeatures.Count; i++)
{
//查找此生成器形状和给定形状的并集。此生成器的形状将根据结果进行更新。
pEnvBuilder.UnionOf(pListFeatures[i].Geometry.Extent);
}
//缩放到提供的几何体。即使几何体不规则,下面的函数会自动找出可以包含进所有外形的矩形,并向外扩展50像素。
await MyMapView.SetViewpointGeometryAsync(pEnvBuilder.ToGeometry(), 50);
//显示选择要素的属性。
}
catch (Exception ex)
{
MessageBox.Show("An error occurred.\n" + ex, "Sample error");
}
}
// 简单查询
private async void easyQuery(object sender, RoutedEventArgs e)
{
string sQueryFieldName = "Name"; //图层字段名
string stateName = "New York"; //图层字段名里的某个属性
//获取图层,该图层为实例1中加载FeatureLayer数据,默认放在第一层(图层名为 “States” )
// Map.OperationalLayers 获取或设置映射中操作层的集合。
FeatureLayer _featureLayer = MyMapView.Map.OperationalLayers[0] as FeatureLayer;
if (_featureLayer != null)
await QueryStateFeature3(_featureLayer, sQueryFieldName, stateName); // 调用方法
}
点击查询 & identity查询
enum CURRENTOPERATION
{
NullOpe = -1,
SelectQuery = 0,
IdentifyQuery,
PanMap,
};
namespace classTest
{
public partial class MainWindow : Window
{
......
CURRENTOPERATION m_CurOper;
public MainWindow()
{
......
m_CurOper = CURRENTOPERATION.NullOpe;
......
}
......
}
......
}
除了下面代码外,还需要添加上面图中的代码
private async void FunClickQuery(MapPoint pPoint, FeatureLayer _featureLayer)
{
double tol = 3;
// MyMapView.UnitsPerPixel 以贴图单位获取每个设备独立像素的当前大小。
//mapTol 这个容差,就是你鼠标点击的位置,以它为中心,以容差为半径,构建一个几何图形
//你可以试试把容差改大点,然后在点击查询的时候,靠近边界来点,它肯定会选择到以你点的位置为轴心,容差为半径的范围内的图形,并高亮起来
double mapTol = tol * MyMapView.UnitsPerPixel; // 设置选择容差
MapPoint pNormalPoint = pPoint;
//点坐标处理,如果地图是无边界漫游的,则几何体需要正则化
//MyMapView.IsWrapAroundEnabled 指示环绕功能当前是否处于活动状态。要激活环绕,必须将WrapAroundMode属性设置为true,并且MapView控件的SpatialReference必须是支持环绕的SpatialReference。
if (MyMapView.IsWrapAroundEnabled)
{
//GeometryEngine.NormalizeCentralMeridian(pPoint) 将几何体折叠到360度范围内。在地图上启用环绕时,这可能是必需的。如果几何体是封套,则将返回多边形,除非封套为空,否则将返回空封套。
pNormalPoint = (MapPoint)GeometryEngine.NormalizeCentralMeridian(pPoint);
}
//依据点坐标及容差,构建搜索矩形
Envelope selEnv = new Envelope(pNormalPoint.X - mapTol, pNormalPoint.Y - mapTol, pNormalPoint.X +
mapTol, pNormalPoint.Y + mapTol, MyMapView.SpatialReference);
//准备查询条件
QueryParameters pQueryPara = new QueryParameters();
pQueryPara.Geometry = selEnv; // 获取或设置用于筛选结果的几何体。
pQueryPara.SpatialRelationship = SpatialRelationship.Intersects; // 获取或设置几何体参数和要素之间的空间关系类型。
//此方法是确定两个几何图形之间空间关系的几种方法之一。如果两个输入几何体之间存在空间关系,则返回true。如果两个输入几何图形之间不存在空间关系,则返回false。
await _featureLayer.SelectFeaturesAsync(pQueryPara, Esri.ArcGISRuntime.Mapping.SelectionMode.New);
//提取已选择的要素,居中显示
//_featureLayer.GetSelectedFeaturesAsync() 表示异步获取选定功能操作的任务对象。任务结果的值是FeatureQueryResult对象;仅显示选定的功能。
FeatureQueryResult pQueryResult = await _featureLayer.GetSelectedFeaturesAsync();
// 存到列表中
List<Feature> pListFeatures = pQueryResult.ToList();
if (pListFeatures.Count <= 0)
return;
//使用空间引用和空几何体初始化EnveloperBuilder类的新实例。
EnvelopeBuilder pEnvBuilder = new EnvelopeBuilder(_featureLayer.SpatialReference);
for (int i = 0; i < pListFeatures.Count; i++)
{
//查找此生成器形状和给定形状的并集。此生成器的形状将根据结果进行更新。
pEnvBuilder.UnionOf(pListFeatures[i].Geometry.Extent);
}
//缩放到提供的几何体。即使几何体不规则,下面的函数会自动找出可以包含进所有外形的矩形,并向外扩展50像素。
await MyMapView.SetViewpointGeometryAsync(pEnvBuilder.ToGeometry(), 50);
//显示选择要素的属性。
Feature pFeature; string sInfo = "";
//IReadOnlyList 执行地理编码操作以查找给定地址和一组搜索参数的候选位置
IReadOnlyList<Field> pFields = pQueryResult.Fields; // 获取图集的字段。
// 话说点击查询和id查询不应该是唯一的吗,为啥要循环呢
for (int i = 0; i < pListFeatures.Count; i++)
{
pFeature = pListFeatures[i];
// 提取属性方法一, 部分字段值的属性无法获取,容易报错 ===== www重点
//sInfo += "选中的第" + i.ToString() + "个要素的属性\n\r";
//for (int j = 0; j < pFields.Count; j++)
//{
// sInfo += pFields[j].Name + ": ";
// //????下面这一行报错,可以取出ObjectID ,Name的值。字段名为ID, STATE_NAME等,字段值取出报错。
// object temp = pFeature.GetAttributeValue(pFields[j].Name);
// sInfo += pFeature.GetAttributeValue(pFields[j]).ToString() + "\n\r";
//}
// 提取属性方法二, 部分字段值的属性无法获取,pFeature.Attributes; 直接将可提取的字段属性拿出来,不会报错。
IDictionary<string, object> FeatureAttri = pFeature.Attributes; // 就是字段名,字段值 二者形成一个字典对象
string str; object obj;
sInfo += "选中的第" + i.ToString() + "个要素的属性\n\r";
for (int j = 0; j < FeatureAttri.Count; j++)
{
str = FeatureAttri.Keys.ElementAt(j);
obj = FeatureAttri.Values.ElementAt(j);
sInfo += str + ":" + obj.ToString() + "\r\n";
}
}
MessageBox.Show(sInfo);
}
// FunIdentifyQuery 为 Idenify 查询函数
private async void FunIdentifyQuery(System.Windows.Point pPoint, FeatureLayer pFLayer)
{
// 执行Identiy.
//IdentifyLayerResult 获取标识的IdentifyLayerResult的列表。
//GeoView.IdentifyLayerAsync Method(Layer, Point, Double, Boolean) 在指定图层上启动标识操作,该操作将仅返回单个可见的最上面的地理元素。
IdentifyLayerResult myIdentifyResult = await MyMapView.IdentifyLayerAsync(pFLayer, pPoint, 20, false);
// 如果结果为空,退出
if (!myIdentifyResult.GeoElements.Any())
{
return;
}
//修改以下代码,循环遍历所有选中的要素
// 得到查询结果中的第一个图层
Feature identifiedFeature = (Feature)myIdentifyResult.GeoElements[0];
//获取要素的属性
IDictionary<string, object> FeatureAttri = identifiedFeature.Attributes;
string str;
string tempStr = "";
object obj;
for (int i = 0; i < FeatureAttri.Count; i++)
{
str = FeatureAttri.Keys.ElementAt(i);
obj = FeatureAttri.Values.ElementAt(i);
tempStr += str + ":" + obj.ToString() + "\r\n";
}
MessageBox.Show(tempStr);
}
private void MenuSelectFeat_Click(object sender, RoutedEventArgs e)
{
m_CurOper = CURRENTOPERATION.SelectQuery; // 点击查询时,更改当前变量值为 0
}
private void MenuIdentify_Click(object sender, RoutedEventArgs e)
{
m_CurOper = CURRENTOPERATION.IdentifyQuery; // id查询时,更改当前变量值为 1
}
private void MyMapView_GeoViewTapped(object sender, Esri.ArcGISRuntime.UI.Controls.GeoViewInputEventArgs e)
{
//点击查询
if (m_CurOper == CURRENTOPERATION.SelectQuery)
{
if (MyMapView.Map.OperationalLayers.Count > 0)
{
FeatureLayer _featureLayer = MyMapView.Map.OperationalLayers[0] as FeatureLayer;
if (_featureLayer != null)
{
FunClickQuery(e.Location, _featureLayer);
}
}
}
//Identify查询
else if (m_CurOper == CURRENTOPERATION.IdentifyQuery)
{
if (MyMapView.Map.OperationalLayers.Count > 0)
{
FeatureLayer _featureLayer = MyMapView.Map.OperationalLayers[0] as FeatureLayer;
if (_featureLayer != null)
{
FunIdentifyQuery(e.Position, _featureLayer);
}
}
}
//考虑编写代码,实现地图漫游功能
else if (m_CurOper == CURRENTOPERATION.PanMap)
{
}
}
3、结果
简单查询
点击查询
identity查询
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!