ArcGIS.Server.9.2.DotNet在地图中显示xml数据(自带例子 九、一)

目的:
1.arcgis server9.2 ADF实现自定义数据源,在地图中显示自定义的xml数据

准备工作:
1.用ArcGis Server Manager或者ArcCatalog发布一个叫usa的Map Service,并且把这个Service启动起来。
2.参考DeveloperKit\SamplesNET\Server\Web_Applications目录下的Common_CustomDataSourceCSharp.zip。

开始:
1.数据显示实现说明:Map控件->MapResourceManager控件->数据源,MapResourceManager控件选择不同的数据源(GISDataSource)加入应用成为Resource,这样Map控件可以通过Resource与数据源进行交互,一个GISDataSource可以有多个Resource,常用的是MapResource 和 GeocodeResource。一个Resource可以有多个Functionatily,通常分为common API和special API两种,data source 决定了resource能做什么(能实现哪些功能的接口或functionality)。这样通过上面的描述就很容易明白一个自定义的xml数据要在Map控件中显示必须先能加入到MapResourceManager控件中成为Resource。
2.在MapResourceManager的MapResourcesItem集合编辑器的Map Resource Definition Editor工具中ESRI已经内置了很多的DataSource类型,在Type选项中有GraphicsLayer、ArcGIS Server Local、OGC (WMS) Service、ArcIMS、ArcGIS Server Internet、ArcWeb Services这几种类型可以选择,现在要显示自定义的xml数据源,就需要为添加新的一个DataSource类型来实现。
3.在MapResourcesItem集合编辑器的Map Resource Definition Editor工具中DataSource类型,是通过一个config的配置文件来实现的,在ArcGIS.Server.9.2.DotNet中这些配置文件放置在ArcGisServer安装目录的DotNet文件内,这里能找到ArcGIS Server Local、GraphicsLayer、ArcIMS等所有DataSource类型的配置文件,可以用记事本打这些文件学习一下它是如何构成的。在这里DotNet文件内添加一个名为ESRI.ArcGIS.ADF.Web.DataSources.REXMLData.config的配置文件用来给我们的工程用,具体的内容和说明如下:

Code

4.有了上面的大概的思路后就开始动手具体功能实现,新建名为CustomDataSource的ASP.NET Web应用程序,然后添加一个Default_REXMLData.aspx页面用来具体功能的展示。
5.在CustomDataSource的解决方案中在添加一个名为REXMLDataSource的类库工程,用来实现自定义DataSource类型和MapResource的功能。同时在CustomDataSource的ASP.NET Web应用程序中添加对这个REXMLDataSource的类库工程的引用。
6.从上面ESRI.ArcGIS.ADF.Web.DataSources.REXMLData.config配置文件看,我们需要实现REXMLDataSource.GISDataSource、REXMLDataSource.MapResource这2个类。
7.新建GISDataSource.cs文件,具体的代码和说明如下:

  1namespace REXMLDataSource
  2{
  3    public class GISDataSource : IGISDataSource
  4    {
  5        private Hashtable m_state;
  6        private string name = string.Empty;
  7        private string dataSourceDefinition = string.Empty;
  8        private string identity = string.Empty;
  9        private Page page = null;
 10        private GISResourceCollection resources = new GISResourceCollection();
 11        bool _initialized = false;
 12
 13        public GISDataSource() 
 14        { }
 15
 16        public GISDataSource(string name, string identity, string dataSourceDefinition)
 17        {
 18            this.name = name;
 19            this.identity = identity;
 20            this.dataSourceDefinition = dataSourceDefinition;
 21        }

 22
 23        public GISDataSource(string name, string dataSourceDefinition): this(name, string.Empty, dataSourceDefinition)
 24        { }
 25
 26        //载入状态,IGISDataSource接口必须实现的方法
 27        //从DataSourceManager关联的Hashtable载入状态
 28        public void LoadState(Hashtable state)
 29        {
 30            m_state = state;
 31        }

 32
 33        //初始化,IGISDataSource接口必须实现的方法
 34        public void Initialize()
 35        {
 36            _initialized = true;
 37        }

 38
 39        //保存状态,IGISDataSource接口必须实现的方法
 40        public Hashtable SaveState()
 41        {
 42            return m_state;
 43        }

 44
 45        //销毁,IGISDataSource接口必须实现的方法
 46        public void Dispose()
 47        {
 48            _initialized = false;
 49        }

 50
 51        //GISDataSource的名称,IGISDataSource接口必须实现的成员
 52        public string Name
 53        {
 54            get return name; }
 55            set { name = value; }
 56        }

 57
 58        //GISDataSource的定义,IGISDataSource接口必须实现的成员
 59        //定义GIS data source信息,通常存储关于GIS data source的定位信息
 60        public string DataSourceDefinition
 61        {
 62            get return dataSourceDefinition; }
 63            set
 64            {
 65                if (dataSourceDefinition != value)
 66                {
 67                    dataSourceDefinition = value;
 68                }

 69            }

 70        }

 71
 72        //GISDataSource的安全标识验证,IGISDataSource接口必须实现的成员
 73        //连接GIS data source的用户认证标识
 74        public string Identity
 75        {
 76            get return identity; }
 77            set { identity = value; }
 78        }

 79
 80        //GISDataSource的Page,IGISDataSource接口必须实现的成员
 81        public Page Page
 82        {
 83            get return page; }
 84            set { page = value; }
 85        }

 86
 87        //GISDataSource的Resources,IGISDataSource接口必须实现的成员
 88        public GISResourceCollection Resources
 89        {
 90            get return resources; }
 91            set { resources = value; }
 92        }

 93
 94        //GISDataSource的状态,IGISDataSource接口必须实现的成员
 95        //data source的状态存储,Resources和functionalities关联这个GIS data source的状态都被存储在这里,DataSourceManager控件会以哈希表存储所有的data source的状态
 96        public Hashtable State
 97        {
 98            get
 99            {
100                return m_state;
101            }

102        }

103
104        //GISDataSource的是否初始化标识,IGISDataSource接口必须实现的成员
105        public bool Initialized
106        {
107            get return _initialized; }
108        }

109
110        //获取有效的ResourceDefinitions,IGISDataSource接口必须实现的方法
111        public string[] GetAvailableResourceDefinitions(System.Type resourceType)
112        {
113            throw new Exception("The method or operation is not implemented.");
114        }

115
116        //建立Resource,IGISDataSource接口必须实现的方法
117        public IGISResource CreateResource(string resourceDefinition, string name)
118        {
119            throw new Exception("The method or operation is not implemented.");
120        }

121    }

122
123}

124
8.新建MapResource.cs文件,具体的代码和说明如下:
  1namespace REXMLDataSource
  2{
  3    //MapResource实现IMapResource接口,而IMapResource实现了IGISResource接口,所以MapResource必须实现IMapResource和IGISResource的必要成员
  4    public class MapResource : IMapResource
  5    {
  6        public MapResource() { }
  7        public MapResource(string name, GISDataSource dataSource)
  8        {
  9            this.name = name;
 10            this.dataSource = dataSource;
 11        }

 12
 13        private GraphicsDataSet graphics = null;
 14
 15        public GraphicsDataSet Graphics
 16        {
 17            get return graphics; }
 18        }

 19
 20        private IMapInformation mapInformation = null;
 21        private DisplaySettings displaySettings = null;
 22
 23        //IMapResource接口必须实现的成员,Map信息
 24        public IMapInformation MapInformation
 25        {
 26            get return mapInformation; }
 27            set { mapInformation = value; }
 28        }

 29
 30        //IMapResource接口必须实现的成员,地图显示设置
 31        public DisplaySettings DisplaySettings
 32        {
 33            get return displaySettings; }
 34            set { displaySettings = value; }
 35        }

 36
 37
 38        bool initialized = false;
 39        private string name = string.Empty;
 40        private string resourceDefinition = string.Empty;
 41        private IGISDataSource dataSource = null;
 42        private GISFunctionalityCollection functionalities = new GISFunctionalityCollection();
 43        private int validationtimeout = 0;
 44
 45        //IGISResource接口必须实现的成员,Resource初始化的超时时间
 46        public int ValidationTimeout
 47        {
 48            get return validationtimeout; }
 49            set { validationtimeout = value; }
 50        }

 51
 52        //IGISResource接口必须实现的成员,Resource名称
 53        public string Name
 54        {
 55            get return name; }
 56            set { name = value; }
 57        }

 58
 59        //IGISResource接口必须实现的成员,Resrouce定义字符串
 60        public string ResourceDefinition
 61        {
 62            get return resourceDefinition; }
 63            set { resourceDefinition = value; }
 64        }

 65
 66        //IGISResource接口必须实现的成员,Resource的Data Source
 67        public IGISDataSource DataSource
 68        {
 69            get return dataSource; }
 70            set { dataSource = value; }
 71        }

 72
 73        //IGISResource接口必须实现的成员,Resrource的Functionality集合
 74        public GISFunctionalityCollection Functionalities
 75        {
 76            get return functionalities; }
 77            set { functionalities = value; }
 78        }

 79
 80        //IGISResource接口必须实现的成员,判定是否支持各类的Functionality
 81        public bool SupportsFunctionality(System.Type functionalityType)
 82        {
 83            if (functionalityType == typeof(ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality))
 84            {
 85                return true;
 86            }

 87            else if (functionalityType == typeof(ESRI.ArcGIS.ADF.Web.DataSources.IMapTocFunctionality))
 88            {
 89                return true;
 90            }

 91            else if (functionalityType == typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality))
 92            {
 93                return true;
 94            }

 95            else
 96            {
 97                return false;
 98            }
 
 99        }

100
101        //IGISResource接口必须实现的成员,创建各种Functionality
102        public IGISFunctionality CreateFunctionality(System.Type functionalityType, string functionalityName)
103        {
104            IGISFunctionality gisfunctionality = null;
105            if (functionalityType == typeof(ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality))
106            {
107                //MapFunctionality,具体见MapFunctionality.cs
108                gisfunctionality = new MapFunctionality(functionalityName, this);
109            }

110            else if (functionalityType == typeof(ESRI.ArcGIS.ADF.Web.DataSources.IMapTocFunctionality))
111            {
112                //MapTocFunctionality,具体见MapTocFunctionality.cs
113                gisfunctionality = new MapTocFunctionality(functionalityName, this);
114            }

115            else if (functionalityType == typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality))
116            {
117                //QueryFunctionality,具体见QueryFunctionality.cs
118                gisfunctionality = new QueryFunctionality(functionalityName, this);
119            }

120            else
121            {
122                throw new ArgumentException("functionalityType not supported");
123            }

124            return gisfunctionality;
125        }

126
127        //IGISResource接口必须实现的成员,是否初始化
128        public bool Initialized
129        {
130            get return initialized; }
131        }

132
133        //IGISResource接口必须实现的成员,载入Data Source的状态
134        public void LoadState()
135        {
136            if (dataSource == nullreturn;
137            if (dataSource.State == nullreturn;
138
139            object o = dataSource.State[key];
140            if (o != null)
141            {
142                MapResource mr = o as MapResource;
143                graphics = mr.graphics;
144                mapInformation = mr.mapInformation;
145                displaySettings = mr.displaySettings;
146            }

147        }

148
149        //IGISResource接口必须实现的成员,初始化方法
150        public void Initialize()
151        {
152            if (mapInformation == null)
153            {
154                graphics = new GraphicsDataSet();
155                //设置Resorce的MapInformation,具体见MapInformation.cs
156                mapInformation = new MapInformation(graphics);
157                if (DisplaySettings != null)
158                {
159                    //设置GraphicsDataSet的ImageDescriptor
160                    graphics.ImageDescriptor = displaySettings.ImageDescriptor;
161                }
 
162            }

163            initialized = true;
164            //从Data Source定义中获取xml数据路径
165            string dataSourceConfig = DataSource.DataSourceDefinition;
166            //处理xml数据源
167            ProcessREXML(dataSourceConfig);
168        }

169
170        //IGISResource接口必须实现的成员,保存Resource的状态
171        public void SaveState()
172        {
173            if (dataSource == nullreturn;
174            if (dataSource.State == nullreturn;
175            dataSource.State[key] = this;
176        }

177
178        //IGISResource接口必须实现的成员,销毁方法
179        public void Dispose()
180        {
181            initialized = false;
182        }

183
184        //IGISResource接口必须实现的成员,清除Resource的状态
185        public void ClearState()
186        {
187            if (DataSource == null || DataSource.State == nullreturn;
188            DataSource.State[key] = null;
189        }

190
191        //本Resource存储在hashtable中的key
192        private string key
193        {
194            get
195            {
196                string tmp = this.GetType().ToString() + ":" + name;
197                return (tmp);
198            }

199        }

200
201        private void ProcessREXML(string dataSourceConfig)
202        {
203            try
204            {
205                //读取xml文件
206                XmlDocument doc = new XmlDocument();
207                doc.Load(dataSourceConfig);
208                XmlNode root = doc.DocumentElement;
209
210                //获取LAYER信息
211                XmlNode layerNode = root.SelectSingleNode("LAYER");
212                string layername = layerNode.Attributes.GetNamedItem("name").Value;
213                string layerid = layerNode.Attributes.GetNamedItem("id").Value;
214
215                ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer glayer = null;
216                bool gvisibility = true;
217
218                //从GraphicsDataSet查找名为layername FeatureGraphicsLayer,如果已有就记录显示状态并且清除layername FeatureGraphicsLayer
219                if (graphics.Tables.Contains(layername))
220                {
221                    if (graphics.Tables[layername] is FeatureGraphicsLayer)
222                    {
223                        //记录显示状态
224                        FeatureGraphicsLayer fgl = (FeatureGraphicsLayer)graphics.Tables[layername];
225                        gvisibility = fgl.Visible;
226                    }

227                    //清除layername FeatureGraphicsLayer
228                    graphics.Tables.Remove(layername);
229                }

230
231                //新见FeatureGraphicsLayer并设置属性
232                glayer = new ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer();
233                glayer.TableName = layername;
234                glayer.FeatureType = FeatureType.Point;
235                glayer.Visible = gvisibility;
236
237                //获取颜色、类型、宽、外边框颜色
238                XmlNode rendererNode = layerNode.SelectSingleNode("SIMPLERENDERER");
239                XmlNode markerNode = rendererNode.SelectSingleNode("SIMPLEMARKERSYMBOL");
240                string markercolor = markerNode.Attributes.GetNamedItem("color").Value;
241                string markertype = markerNode.Attributes.GetNamedItem("type").Value;
242                string markerwidth = markerNode.Attributes.GetNamedItem("width").Value;
243                string markeroutlinecolor = markerNode.Attributes.GetNamedItem("outlinecolor").Value;
244
245                //创建用来显示的图标
246                ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleMarkerSymbol sms = new ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleMarkerSymbol();
247
248                //rgb颜色
249                string[] markerrgb = markercolor.Split(',');
250                int markerr = Int32.Parse(markerrgb[0]);
251                int markerg = Int32.Parse(markerrgb[1]);
252                int markerb = Int32.Parse(markerrgb[2]);
253                //图标颜色
254                sms.Color = System.Drawing.Color.FromArgb(markerr, markerg, markerb);
255
256                //图标形状
257                switch (markertype)
258                {
259                    case "circle":
260                        sms.Type = ESRI.ArcGIS.ADF.Web.Display.Symbol.MarkerSymbolType.Circle;
261                        break;
262                    case "square":
263                        sms.Type = ESRI.ArcGIS.ADF.Web.Display.Symbol.MarkerSymbolType.Square;
264                        break;
265                    case "triangle":
266                        sms.Type = ESRI.ArcGIS.ADF.Web.Display.Symbol.MarkerSymbolType.Triangle;
267                        break;
268                    case "star":
269                        sms.Type = ESRI.ArcGIS.ADF.Web.Display.Symbol.MarkerSymbolType.Star;
270                        break;
271                    default:
272                        break;
273                }

274
275                int markerwidthInt;
276                if (!Int32.TryParse(markerwidth, out markerwidthInt))
277                {
278                    markerwidthInt = 10;
279                }

280                //图标宽
281                sms.Width = markerwidthInt;
282
283                string[] markeroutrgb = markeroutlinecolor.Split(',');
284                int markeroutr = Int32.Parse(markeroutrgb[0]);
285                int markeroutg = Int32.Parse(markeroutrgb[1]);
286                int markeroutb = Int32.Parse(markeroutrgb[2]);
287                //图标外框颜色
288                sms.OutlineColor = System.Drawing.Color.FromArgb(markeroutr, markeroutg, markeroutb);
289
290                ESRI.ArcGIS.ADF.Web.Display.Renderer.SimpleRenderer sr = new ESRI.ArcGIS.ADF.Web.Display.Renderer.SimpleRenderer(sms);
291                glayer.Renderer = sr;
292
293                //获取FEATURES
294                XmlNode featuresNode = layerNode.SelectSingleNode("FEATURES");
295                XmlNodeList featureNodes = featuresNode.SelectNodes("FEATURE");
296
297                //获取SHAPE的字段属性建立GraphicElement
298                for (int t = 0; t < featureNodes.Count; ++t)
299                {
300                    System.Data.DataRow datarow = null;
301
302                    XmlNodeList flds = featureNodes[t].SelectNodes("FIELD");
303                    for (int s = 0; s < flds.Count; s++)
304                    {
305                        // 如果是SHAPE就建立DataRow
306                        if (flds[s].Attributes["name"].Value == "SHAPE")
307                        {
308                            XmlNodeList fldvalues = flds[s].SelectSingleNode("FIELDVALUE").ChildNodes;
309                            if (fldvalues.Count < 1)
310                            {
311                                break;
312                            }

313                            else if (fldvalues.Count == 1)
314                            {
315                                XmlNode fldvalue = fldvalues[0];
316                                if (fldvalue.Name == "POINT")
317                                {
318                                    double dx = Double.Parse(fldvalue.Attributes["x"].Value);
319                                    double dy = Double.Parse(fldvalue.Attributes["y"].Value);
320
321                                    ESRI.ArcGIS.ADF.Web.Geometry.Point point = new ESRI.ArcGIS.ADF.Web.Geometry.Point(dx, dy);
322                                    datarow = glayer.Add(point);
323                                }

324                            }

325                            else if (fldvalues.Count > 1)
326                            {
327
328                            }

329                        }

330                        else//否则作为属性
331                        {
332                            
333                            string fldname = flds[s].Attributes["name"].Value;
334                            if (!glayer.Columns.Contains(fldname))
335                            {
336                                System.Data.DataColumn dcol = new System.Data.DataColumn("Status", System.Type.GetType("System.String"));
337                                glayer.Columns.Add(dcol);
338                            }

339                            XmlNode fldvalue = flds[s].SelectSingleNode("FIELDVALUE");
340                            string dvalue = fldvalue.Attributes["valuestring"].Value;
341                            if ((dvalue != null|| (dvalue != String.Empty))
342                            {
343                                datarow[fldname] = dvalue;
344                            }

345                                
346                        }

347                    }

348                }

349                //把生成的GraphicElement添加到GraphicsDataSet
350                graphics.Tables.Add(glayer);
351
352                
353            }

354            catch (Exception ex)
355            {
356                throw new Exception("Exception: unable to load rexml data. " + ex.Message);
357
358            }

359
360        }

361    }

362}

363

9.MapResource类的几个主要方法执行顺序帮助理解:MapResource()->LoadState()->Initialize()->SupportsFunctionality()->CreateFunctionality()->SupportsFunctionality()->SaveState()->Dispose()
10.在MapResource类相关的MapInformation、MapFunctionality、MapTocFunctionality、QueryFunctionality4个类的实现可以参考Common_CustomDataSourceCSharp.zip样例,代码比较多比较简单这里就不详细说了。
11.xml数据内容如下:
Code
12.这样就完成了一个Data Srouce以及Reaource的定义,接下在我们在页面上加载显示这个数据源。
13.在CustomDataSource的ASP.NET Web应用程序的Default_REXMLData.aspx页面中添加Map1、MapResourceManager1、Toc13个控件,然后做相应的设置,把上发布的usa的Map Service添加到MapResourceManager1中设置为ArcGIS Server Internet类型,名称为Server Resource,具体设置可以参考前面的文章。
14.接下来在MapResourceManager1中在Server Resource上面在新增加名为REXML Resource,在弹出的Map Resource Definition Editor中Type:选择REXML Data就是上面添加到DotNet文件内的ESRI.ArcGIS.ADF.Web.DataSources.REXMLData.config中定义的名字,在Data Source:输入上面的那个xml的地址,如:D:\rexml_point_wgs84.xml,然后确定就完成了设置。这里的Data Source为了方便是输入的方式了,最好的做法可以参考Common_CustomDataSourceCSharp.zip样例为它做一个xml文件选择界面,具体的参考CustomDataSource_CSharp\REXMLDataSource_CSharp\Design\DataSourceDefinitionEditorFormREXML.cs,是一个Winform的选择节目,只有在config文件配置一下,就可以在
Map Resource Definition Editor中调用自己定制的编辑器。
15.运行查看效果,可以看到在usa的地图上有4个绿色的五星,这4个5星就是从xml里定义的点。
16.通过自己实现GISData Source、MapResource、MapFunctionality的定义和实现就对ADF的WebControls、GISData SourceMapResourceMapFunctionality、具体的地图数据 这几者之间的关系就非常容易理解了,这样就让一些特殊的数据格也可以在ADF中使用了大大提高了数据的灵活性。
posted @ 2008-08-31 13:35  水的右边  阅读(4924)  评论(26编辑  收藏  举报