ArcGIS Engine开发之属性查询
ArcGIS Engine开发之属性查询
来自:http://www.cnblogs.com/dongteng/p/5925120.html
属性查询即基于空间数据的属性数据的查询,通过用户提交SQL语言中的where语句定义的查询条件,对属性数据进行搜索,从而得到查询结果的操作。
相关的类与接口
与属性查询功能相关的类主要有QureyFilter、QueryDef、Cursor、FeatureCursor等。涉及的接口有IQueryFilter、IQueryDef、ICursor、IFeatureCursor以及IFeatureSelection等。以上的类和接口都位于ArcGIS.Geodatabase命名空间中。
1.QueryFilter类
该类用于根据属性值或关系来过滤数据,它实现了IQueryFilter接口,该接口主要有以下的接口和方法。
1)WhereClause属性
设置用来过滤数据的where条件子句。该子句使用SQL表达式来定义过滤数据的条件,可以使用运算符、通配符、函数等字符来构成where子句。具体的语法根据数据源的不同而有所不同。
2)SubField属性
定义用于数过滤的属性字段列表,如果列表有多项,则每项之间用英文逗号隔开,默认为*,意味着返回结果中包含所有字段,否则可以自定义需要返回的字段。
2.QueryDef类
该类是ESRI的查询定义类,为ArcGIS Engine中的Class类,不能被直接创建,可以由IFeatureWorkspace接口的CreateQueryDef方法创建。它实现了IQueryDef接口,该接口的成员用来操作基于属性的查询,主要有一下的属性和方法:
1)Tables属性:该属性定义所查询表的名称和列表,如果列表有多项,则每项之间用英文逗号隔开。
2)WhereClause属性:该属性的方法与IQueryFilter接口中的WhereClause属性的用法相同。
3)SubField属性:该属性的用法与IQueryFilter接口中的SubField属性用法相同。
4)Evaluate方法:该方法定义的查询并返回结果集的游标,该游标为ICursor接口类型。
3.Cursor类
该类是ESRI的游标类,为ArcGIS Engine中的Class类,不能直接被创建,可以由相关接口中的方法创建。
游标的解释:游标是数据库中的概念,他是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,用户可以从游标中逐一获取上述的执行结果。从本质上讲,游标是一种能够从包括多条数据记录的结果集中每次提取一条记录的机制,因此,ArcGIS中使用游标的概念来操作各类查询的结果。游标的接口主要包括ICursor接口和IFeatureCursor接口,IFeatureCursor接口继承与ICursor接口,ICursor接口主要用于操作数据行,IFeatureCursor接口主要用来操作要素Feature。
Cursor类主要实现了ICursor接口,该接口的成员用来获取枚举的行和列的集合,或用来更新、删除和插入数据行。使用NextRow方法,将游标的位置向前移动一位,并返回该位置的行对象。
4.FeatureCursor类
该类是ESRI的要素游标类,为ArcGIS Eninge中的Class类,不能被直接创建,同样可以由相关接口中的方法创建。它实现了IFeatureCursor接口,该接口的成员的用法和ICursor接口的成员用法类似,区别是其操作的对象是要素。重要使用NextFeature方法(IFeature NextFeature),将游标的位置向前移动一位,并返回给位置的要素对象。
5.FeatureLayer类
该类主要操作要素的集合及要素的可视化表达,它实现了IFeatureLayer接口和IFeatureSelection接口。
1)IFeatureLayer接口:该接口的成员主要是要素图层各类常用属性和操作。其与查询相关的属性和方法有:
(1)Selectable属性:用于获取或设置图层是否可被选择。
(2)FeatureClass属性:用于获取或设置图层的要素类
(3)Search方法:根据设置的查询条件创建查询结果的游标。其参数包括IQueryFilter接口的查询过滤器,以及布尔类型的参数来确定游标是否需要被回收。该方法的返回值为IFeatureCursor类型
2)IFeatureSelection接口:该接口的成员用来控制图层的要素选择集,其中与查询相关的属性和方法有:
(1)SelectionFeature方法:用于根据设置的查询条件和选择方法等来选择要素。其参数包括IQueryFilter接口的查询过滤器,esriSelectionResultEnum枚举类型的选择集生成方法,以及布尔型的参数控制是否只选择一个要素。该方法没有返回值。
(2)SelectionSet属性。设置或获取单个矢量图层的选择集,其值为ISelectionSet接口类型。
6.FeatureClass类
该类是Engine中的Class类,不能被直接创建,但可以通过多种方法获取某个图层的要素类,如果使用IFeatureLayer接口的FeatureClass属性。它实现了IFeatureClass接口,该接口的成员用于控制要素类的属性和行为,主要的方法:
1)search方法:根据查询条件进行查询并返回结果游标,该方法的用法与IFeatureLayer接口中的Search方法的用法相同。
2)Select方法:根据查询条件选择相应的要素,并将其放置在选择集中。其参数包括IQueryFilter接口查询过滤器,定义选择方式参数,定义查询的工作区的参数。其返回值为ISelectionSet接口类型。
最终运行截图
代码:
1 public partial class FormQueryByAttribute : DevExpress.XtraEditors.XtraForm 2 { 3 //变量定义 4 private IMap currentMap;//当前MapControl控件的Map对象 5 private IFeatureLayer currentFeatureLayer;//设置临时类变量来使用IFeatureLayer接口的当前图层对象 6 private string currentFileName;//设置临时类变量来存储字段名称 7 /// <summary> 8 /// 获得当前MapControl控件中的对象 9 /// </summary> 10 public IMap CurrentMap 11 { 12 set 13 { 14 currentMap = value; 15 } 16 } 17 public FormQueryByAttribute() 18 { 19 20 InitializeComponent(); 21 } 22 #region 窗体加载Load事件 23 private void FormQueryByAttribute_Load(object sender, EventArgs e) 24 { 25 try 26 { 27 //将当前图层列表清空 28 comBoxLayerName.Items.Clear(); 29 string layerName;//设置临时变量存储图层名称 30 //对Map中的每个图层进行判断并加载名称 31 for (int i = 0; i < currentMap.LayerCount; i++) 32 { 33 //如果该图层为图层组类型,则分别对所包含的每个图层进行操作 34 if (currentMap.get_Layer(i) is GroupLayer) 35 { 36 //使用ICompositeLayer接口进行遍历操作 37 ICompositeLayer compositeLayer = currentMap.get_Layer(i) as ICompositeLayer; 38 for (int j = 0; j < compositeLayer.Count; j++) 39 { 40 //将图层的名称添加到comboxLayerName中 41 layerName = compositeLayer.get_Layer(j).Name; 42 comBoxLayerName.Items.Add(layerName); 43 } 44 } 45 //如果图层不是图层组类型,则直接添加名称 46 else 47 { 48 layerName = currentMap.get_Layer(i).Name; 49 comBoxLayerName.Items.Add(layerName); 50 } 51 } 52 //将comboxLayerName控件的默认选项设置为第一个图层名称 53 comBoxLayerName.SelectedIndex = 0; 54 //将comboxselectMethod控件的默认选项设置为第一种选择方式 55 comBoxSelectMethod.SelectedIndex = 0; 56 } 57 catch { } 58 } 59 #endregion 60 #region 图层名称下拉框中选择的图层发生改变时触发事件 61 private void comBoxLayerName_SelectedIndexChanged(object sender, EventArgs e) 62 { 63 //首先将字段列表和字段值列表清空 64 ListBoxFields.Items.Clear(); 65 ListBoxValues.Items.Clear(); 66 IField field;//设置临时变量存储使用的IField接口对象 67 for (int i = 0; i < currentMap.LayerCount; i++) 68 { 69 if (currentMap.get_Layer(i) is GroupLayer) 70 { 71 ICompositeLayer compositeLayer = currentMap.get_Layer(i) as ICompositeLayer; 72 for (int j = 0; i < compositeLayer.Count; j++) 73 { 74 //判断图层的名称是否与comBoxLayerName控件中选择的图层名称相同 75 if (compositeLayer.get_Layer(j).Name == comBoxLayerName.SelectedItem.ToString()) 76 { 77 //如果相同则设置为整个窗体使用的IFeatureLayer接口对象 78 currentFeatureLayer = compositeLayer.get_Layer(j) as IFeatureLayer; 79 break; 80 } 81 } 82 } 83 else 84 { 85 //判断图层的名称是否与comboxLayerName控件中选择的图层名称相同 86 if (currentMap.get_Layer(i).Name == comBoxLayerName.SelectedItem.ToString()) 87 { 88 //如果相同则设置为整个窗体所使用的IFeatureLayer接口对象 89 currentFeatureLayer = currentMap.get_Layer(i) as IFeatureLayer; 90 break; 91 } 92 } 93 } 94 //使用IFeatureClass接口对该图层的所有属性字段进行遍历,并填充listboxField控件 95 for (int i = 0; i < currentFeatureLayer.FeatureClass.Fields.FieldCount; i++) 96 { 97 //根据索引值获取图层的字段 98 field = currentFeatureLayer.FeatureClass.Fields.get_Field(i); 99 //排除SHAPE字段,并在其他字段名称前后添加字符“\” 100 if (field.Name.ToUpper() != "SHAPE") 101 ListBoxFields.Items.Add("\"" + field.Name + "\""); 102 } 103 //更新labelSelectResult控件中的图层名称信息 104 labSelectResult.Text = currentFeatureLayer.Name + "WHERE:"; 105 //将显示where语句的文本内容清除 106 txtSelectResult.Clear(); 107 } 108 #endregion 109 #region 选择方式下拉框中选择的图层发生改变时触发事件 110 private void comBoxSelectMethod_SelectedIndexChanged(object sender, EventArgs e) 111 { 112 //首先将listboxvalue控件中的字段属性清空 113 ListBoxValues.Items.Clear(); 114 //将获取唯一值按钮设置为可用状态 115 if (btnOnlyAttributeValue.Enabled == true) 116 { 117 btnOnlyAttributeValue.Enabled = true; 118 } 119 //设置窗体可用的字段名称 120 string str = ListBoxFields.SelectedItem.ToString(); 121 str = str.Substring(1); 122 str = str.Substring(0,str.Length-1); 123 currentFileName = str; 124 } 125 #endregion 126 #region 获取唯一值按钮的单击事件 127 private void btnOnlyAttributeValue_Click(object sender, EventArgs e) 128 { 129 //将图层的某个字段进行唯一值获取操作,并将所有的唯一值显示在listBoxValues控件中 130 try 131 { 132 //使用FeatureClass对象的IDataset接口来获取dataset和workspace的信息 133 IDataset dataset = (IDataset)currentFeatureLayer.FeatureClass; 134 //使用IQueryDef接口的对象来定义和查询属性信息。通过IWorkspace接口的CreateQueryDef()方法创建该对象。 135 IQueryDef queryDef = ((IFeatureWorkspace)dataset.Workspace).CreateQueryDef(); 136 //设置所需查询的表格名称为dataset的名称 137 queryDef.Tables = dataset.Name; 138 //设置查询的字段名称。可以联合使用SQL语言的关键字,如查询唯一值可以使用DISTINCT关键字。 139 queryDef.SubFields = "DISTINCT (" +currentFileName + ")"; 140 //执行查询并返回ICursor接口的对象来访问整个结果的集合 141 ICursor cursor = queryDef.Evaluate(); 142 //使用IField接口获取当前所需要使用的字段的信息 143 IFields fields = currentFeatureLayer.FeatureClass.Fields; 144 IField field = fields.get_Field(fields.FindField(currentFileName)); 145 146 //对整个结果集合进行遍历,从而添加所有的唯一值 147 //使用IRow接口来操作结果集合。首先定位到第一个查询结果。 148 IRow row = cursor.NextRow(); 149 //如果查询结果非空,则一直进行添加操作 150 while (row != null) 151 { 152 //对String类型的字段,唯一值的前后添加'和',以符合SQL语句的要求 153 if (field.Type == esriFieldType.esriFieldTypeString) 154 { 155 ListBoxValues.Items.Add("\'" + row.get_Value(0).ToString() + "\'"); 156 } 157 else 158 { 159 ListBoxValues.Items.Add(row.get_Value(0).ToString()); 160 } 161 //继续执行下一个结果的添加 162 row = cursor.NextRow(); 163 } 164 } 165 catch (Exception ex) 166 { 167 168 } 169 170 } 171 #endregion 172 #region 各按钮的单击事件 173 //关闭 174 private void btnClose_Click(object sender, EventArgs e) 175 { 176 this.Close(); 177 } 178 //清除 179 private void btnClear_Click(object sender, EventArgs e) 180 { 181 txtSelectResult.Clear(); 182 } 183 //在字段列表中双击属性字段名称时发生 184 private void ListBoxFields_MouseDoubleClick(object sender, MouseEventArgs e) 185 { 186 //在结果中添加字段的名称 187 txtSelectResult.Text += ListBoxFields.SelectedItem.ToString(); 188 } 189 //字段值列表中双击添加 190 private void ListBoxValues_MouseDoubleClick(object sender, MouseEventArgs e) 191 { 192 txtSelectResult.Text += ListBoxValues.SelectedItem.ToString(); 193 } 194 //点击“+”时 195 private void btnEqual_Click(object sender, EventArgs e) 196 { 197 //添加到结果文本框中 198 txtSelectResult.Text += " " + btnEqual.Text + " "; 199 200 } 201 //点击“Like”时 202 private void btnLike_Click(object sender, EventArgs e) 203 { 204 txtSelectResult.Text += " " + btnLike.Text + " "; 205 } 206 // 207 private void btnDayu_Click(object sender, EventArgs e) 208 { 209 txtSelectResult.Text += "" + btnDayu.Text + ""; 210 211 } 212 213 private void btnDayuEqual_Click(object sender, EventArgs e) 214 { 215 txtSelectResult.Text +=" "+btnDayuEqual.Text+" "; 216 } 217 218 private void btnAnd_Click(object sender, EventArgs e) 219 { 220 txtSelectResult.Text += "" + btnAnd.Text + ""; 221 } 222 223 private void btnXiYu_Click(object sender, EventArgs e) 224 { 225 txtSelectResult.Text += "" + btnXiYu.Text + ""; 226 } 227 228 private void btnXiaoyuEqual_Click(object sender, EventArgs e) 229 { 230 txtSelectResult.Text += "" + btnXiaoyuEqual.Text + ""; 231 } 232 233 private void btnUnderLine_Click(object sender, EventArgs e) 234 { 235 txtSelectResult.Text += "" + btnUnderLine.Text + ""; 236 } 237 238 private void btnPersent_Click(object sender, EventArgs e) 239 { 240 txtSelectResult.Text += "" + btnPersent.Text + ""; 241 } 242 243 private void btnIs_Click(object sender, EventArgs e) 244 { 245 txtSelectResult.Text += "" +btnIs.Text+""; 246 } 247 248 private void btnNot_Click(object sender, EventArgs e) 249 { 250 txtSelectResult.Text += "" + btnNot.Text + ""; 251 } 252 253 private void btnNoEqual_Click(object sender, EventArgs e) 254 { 255 txtSelectResult.Text += "" + btnNoEqual.Text + ""; 256 } 257 #endregion 258 #region 定义执查询的方法 259 private void SelectFeatureByAttribute() 260 { 261 //使用FeatureLayer对象的IFeatureSelection接口执行查询操作。进行接口的转换。 262 IFeatureSelection featureSelection=currentFeatureLayer as IFeatureSelection; 263 //新建IQueryFilter接口的对象来进行Where语句定义 264 IQueryFilter queryFilter=new QueryFilterClass(); 265 //设置Where语句内容 266 queryFilter.WhereClause=txtSelectResult.Text; 267 //通过接口转换使用Map对象的IActiveView接口来部分刷新地图窗口,从而高亮显示查询结果 268 IActiveView activeView =currentMap as IActiveView ; 269 //根据查询选择方式的不同,得到不同的选择集 270 switch(comBoxSelectMethod.SelectedIndex) 271 { 272 //在新建选择集的情况下 273 case 0: 274 //首先使用IMap接口的ClearSelection()方法清空地图选择集 275 currentMap.ClearSelection(); 276 //根据定义的where语句使用IFeatureSelection接口的SelectFeature方法选择要素,并将其添加到选择集中 277 featureSelection.SelectFeatures(queryFilter,esriSelectionResultEnum.esriSelectionResultNew,false); 278 break; 279 case 1: 280 featureSelection .SelectFeatures(queryFilter,esriSelectionResultEnum.esriSelectionResultAdd,false); 281 break; 282 case 2: 283 featureSelection .SelectFeatures(queryFilter,esriSelectionResultEnum.esriSelectionResultXOR,false); 284 break; 285 case 3: 286 featureSelection .SelectFeatures(queryFilter,esriSelectionResultEnum.esriSelectionResultAdd,false); 287 break; 288 //默认为新建选择集的情况 289 default: 290 featureSelection .SelectFeatures(queryFilter,esriSelectionResultEnum.esriSelectionResultNew,false); 291 break; 292 } 293 //部分刷新操作,只刷新地理选择集的内容 294 activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection,null,activeView.Extent); 295 } 296 #endregion 297 //确定按钮 298 private void btnOk_Click(object sender, EventArgs e) 299 { 300 try 301 { 302 SelectFeatureByAttribute(); 303 this.Close(); 304 } 305 catch { } 306 } 307 //应用按钮 308 private void btnApply_Click(object sender, EventArgs e) 309 { 310 SelectFeatureByAttribute(); 311 } 312 313 }
代码2:主窗口中按钮事件
1 #region 属性查询的按钮事件 2 private void btnSearchAttribute_ItemClick(object sender, ItemClickEventArgs e) 3 { 4 //创建新建属性查询窗体 5 FormQueryByAttribute frmQureyByAttribute = new FormQueryByAttribute(); 6 //将当前主窗体的MapControl控件中的Map对象赋值给FormQueryByAttribute窗体的CurrentMap属性 7 frmQureyByAttribute.CurrentMap = mainMapControl.Map; 8 //显示属性查询窗体 9 frmQureyByAttribute.Show(); 10 } 11 #endregion