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