GIS中的查询分析功能是非常重要的,本节将实现这些功能。
1属性及空间查询
在Forms文件夹右击点击“添加”—>“Windows窗体”,添加两个窗体,分别用于空间查询和属性查询,参数设置如下表。
窗体名称(Name) |
Text属性 |
描述 |
SpatialQueryForm |
空间查询 |
用于空间查询参数设置 |
AttributeQueryForm |
属性查询 |
用于属性查询参数设置 |
同时在主窗体上的菜单项上添加一二级菜单。
查询(menuQuery)
……属性查询(menuAttributeQuery)
……空间查询(menuSpatialQuery)
实现属性查询,首先打开“属性查询”窗体的设计器。添加三个Label控件,两个ComboBox,两个Button和一个TextBox。各控件属性设置如下:
名称(Name) |
Text属性 |
描述 |
lblLayer |
选择图层: |
标签 |
lblField |
字段名称: |
标签 |
lblFind |
查找内容: |
标签 |
cboLayer |
MapControl中的图层名称 |
|
cboField |
cboLayer选中图层的所有字段名称 |
|
txtValue |
输入的查询对象名称 |
|
btnOk |
查找 |
查询按钮 |
btnCancel |
取消 |
取消查询按钮 |
界面效果如下:
进入窗体的代码编辑界面,首先添加三个引用:
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
然后定义两个成员变量,一个用于存储地图数据,一个用于存储当前选中图层,如下
//地图数据
private AxMapControl mMapControl;
//选中图层
private IFeatureLayer mFeatureLayer;
然后修改其构造函数,构造函数中添加一个参数MapControl,用于获取MapControl中的数据,如下所示:
public AttributeQueryForm(AxMapControl mapControl)
{
InitializeComponent();
this.mMapControl = mapControl;
}
在窗体的Load事件中添加代码,用于初始化cboLayer,获取MapControl中的图层名称,如下:
//MapControl中没有图层时返回
if (this.mMapControl.LayerCount <= 0)
return;
//获取MapControl中的全部图层名称,并加入ComboBox
//图层
ILayer pLayer;
//图层名称
string strLayerName;
for (int i = 0; i < this.mMapControl.LayerCount; i++)
{
pLayer = this.mMapControl.get_Layer(i);
strLayerName = pLayer.Name;
//图层名称加入cboLayer
this.cboLayer.Items.Add(strLayerName);
}
//默认显示第一个选项
this.cboLayer.SelectedIndex = 0;
在CboLayer的SelectedIndexChanged事件中添加代码,当选中图层发生变化时,cboField中的字段名称重新获取,代码如下:
//获取cboLayer中选中的图层
mFeatureLayer = mMapControl.get_Layer(cboLayer.SelectedIndex) as IFeatureLayer;
IFeatureClass pFeatureClass = mFeatureLayer.FeatureClass;
//字段名称
string strFldName;
for (int i = 0; i < pFeatureClass.Fields.FieldCount;i++ )
{
strFldName = pFeatureClass.Fields.get_Field(i).Name;
//图层名称加入cboField
this.cboField.Items.Add(strFldName);
}
//默认显示第一个选项
this.cboField.SelectedIndex = 0;
查找按钮添加事件:
private void button1_Click(object sender, EventArgs e)
{
//定义图层,要素游标,查询过滤器,要素
IFeatureCursor pFeatureCursor;
IQueryFilter pQueryFilter;
IFeature pFeature;
IPoint pPoint;
IEnvelope pEnv;
pEnv = mMapControl.ActiveView.Extent;
pPoint = new PointClass();
pPoint.X = pEnv.XMin + pEnv.Width / 2;
pPoint.Y = pEnv.YMin + pEnv.Height / 2;
if (this.mMapControl.LayerCount <= 0)
return;
//获取图层
mFeatureLayer = mMapControl.get_Layer(cboLayer.SelectedIndex) as IFeatureLayer;
//清除上次查询结果
this.mMapControl.Map.ClearSelection();
this.mMapControl.ActiveView.Refresh();
//pQueryFilter的实例化
pQueryFilter = new QueryFilterClass();
//设置查询过滤条件
pQueryFilter.WhereClause = cboField.Text + "=" + txtValue.Text;
//查询
pFeatureCursor = mFeatureLayer.Search(pQueryFilter, true);
//获取查询到的要素
pFeature = pFeatureCursor.NextFeature();
//判断是否获取到要素
if (pFeature != null)
{
//选择要素
this.mMapControl.Map.SelectFeature(mFeatureLayer, pFeature);
//放大到要素
pFeature.Shape.Envelope.CenterAt(pPoint);
this.mMapControl.Extent = pFeature.Shape.Envelope;
}
else
{
//没有得到pFeature的提示
MessageBox.Show("没有找到相关要素!", "提示");
}
}
取消按钮添加事件:
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
}
点击运行,这样就实现了属性查询的功能。运行效果如下图:
这一小结,我们进一步实现空间查询窗体的设计实现,我们的设想是通过该窗体选择查询的图层和查询的方式,然后将这两个参数传递给主窗体,主窗体实现查询,将查询得到的要素的属性显示在DataGridView控件中,下面开始动手吧。
首先打开“属性查询”窗体的设计器。添加两个Label控件,两个ComboBox,两个Button。各控件属性设置如下:
名称(Name) |
Text属性 |
描述 |
lblLayer |
选择图层: |
标签 |
lblMode |
查询方式: |
标签 |
cboLayer |
|
MapControl中的图层名称 |
cboMode |
|
空间查询的方式 |
btnOk |
确定 |
确定查询按钮 |
btnCancel |
取消 |
取消查询按钮 |
进入窗体的代码编辑界面,首先添加三个引用:
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
然后定义两个成员变量,一个用于存储地图数据,一个用于存储当前选中图层,如下
//获取主界面的MapControl对象
private AxMapControl mMapControl;
//查询方式
public int mQueryMode;
//图层索引
public int mLayerIndex;
然后修改其构造函数,构造函数中添加一个参数MapControl,用于获取MapControl中的数据,如下所示:
public SpatialQueryForm (AxMapControl mapControl)
{
InitializeComponent();
this.mMapControl = mapControl;
}
在窗体的Load事件中添加代码,用于初始化cboLayer,获取MapControl中的图层名称,并初始化查询方式,代码如下:
//MapControl中没有图层时返回
if (this.mMapControl.LayerCount <= 0)
return;
//获取MapControl中的全部图层名称,并加入ComboBox
//图层
ILayer pLayer;
//图层名称
string strLayerName;
for (int i = 0; i < this.mMapControl.LayerCount; i++)
{
pLayer = this.mMapControl.get_Layer(i);
strLayerName = pLayer.Name;
//图层名称加入ComboBox
this.cboLayer.Items.Add(strLayerName);
}
//加载查询方式
this.cboMode.Items.Add("矩形查询");
this.cboMode.Items.Add("线查询");
this.cboMode.Items.Add("点查询");
this.cboMode.Items.Add("圆查询");
//初始化ComboBox默认值
this.cboLayer.SelectedIndex = 0;
this.cboMode.SelectedIndex = 0;
在“确定”按钮添加代码如下:
//设置鼠标点击时窗体的结果
this.DialogResult = DialogResult.OK;
//判断是否存在图层
if (this.cboLayer.Items.Count <= 0)
{
MessageBox.Show("当前MapControl没有添加图层!","提示");
return;
}
//获取选中的查询方式和图层索引
this.mLayerIndex = this.cboLayer.SelectedIndex;
this.mQueryMode = this.cboMode.SelectedIndex;
这样我们就完成了空间查询窗体的设计。由于空间查询的结果需要借助于DataGridView进行显示,我们首先需要添加一个方法LoadQueryResult(AxMapControl mapControl, IFeatureLayer featureLayer, IGeometry geometry),用于获取空间查询得到的要素的属性。在这个方法的参数中,IGeometry是用于空间查询的几何对象,IFeatureLayer是查询要素所在的要素图层,AxMapControl是当前MapControl。我们使用DataTable来存储要素的属性,然后将DataTable中的数据添加到DataGridView进行显示。为了显示效果在主窗体上添加一个Panel控件,把DataGridView控件添加上去,并在Panel控件上添加一个“关闭”按钮。然后把Panel控件Visible属性设置为False。
在这个方法实现过程中,首先利用IFeatureClass的属性字段初始化DataTable,然后利用IGeometry对IFeatureLayer图层进行空间查询返回到要素游标IFeatureCursor中,然后逐个变量要素,将值添加到DataTable。代码如下:
private DataTable LoadQueryResult(AxMapControl mapControl, IFeatureLayer featureLayer, IGeometry geometry)
{
IFeatureClass pFeatureClass = featureLayer.FeatureClass;
//根据图层属性字段初始化DataTable
IFields pFields = pFeatureClass.Fields;
DataTable pDataTable = new DataTable();
for (int i = 0; i < pFields.FieldCount; i++)
{
string strFldName;
strFldName = pFields.get_Field(i).AliasName;
pDataTable.Columns.Add(strFldName);
}