目的:
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
1
<?xml version="1.0" encoding="utf-8" ?>
2
<DataSources>
3
<!--Data Source的Type名称-->
4
<DataSource name="REXML Data">
5
<!--Data Source的定义-->
6
<Implementation assembly="REXMLDataSource" class="REXMLDataSource.GISDataSource"></Implementation>
7
<!--Identity属性编辑器不可用-->
8
<IdentityEditorForm assembly="ESRI.ArcGIS.ADF.Web.UI.WebControls" class="ESRI.ArcGIS.ADF.Web.UI.WebControls.Design.UnusedPropertyEditor"></IdentityEditorForm>
9
<!--Data Source属性编辑器定义-->
10
<DefinitionEditorForm assembly="" class=""></DefinitionEditorForm>
11
<Resource type="Map">
12
<DefinitionEditorForm assembly="" class=""></DefinitionEditorForm>
13
<!--Resource属性-->
14
<Implementation assembly="REXMLDataSource" class="REXMLDataSource.MapResource">
15
</Implementation>
16
</Resource>
17
</DataSource>
18
</DataSources>
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文件,具体的代码和说明如下:
1
namespace 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文件,具体的代码和说明如下:
1
namespace 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 == null) return;
137
if (dataSource.State == null) return;
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 == null) return;
174
if (dataSource.State == null) return;
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 == null) return;
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
1
<?xml version="1.0" encoding="utf-8" ?>
2
<REXML version="1.0">
3
<LAYER id="1" name="mypoints">
4
<SIMPLERENDERER>
5
<SIMPLEMARKERSYMBOL color="0,255,0" type="star" width="16" outlinecolor="0,0,0"/>
6
</SIMPLERENDERER>
7
<FEATURES>
8
<FEATURE featureid="1">
9
<FIELD name="SHAPE" type="-98" >
10
<FIELDVALUE>
11
<POINT x="-117.1" y="34.0" />
12
</FIELDVALUE>
13
</FIELD>
14
<FIELD name="Status" type="12">
15
<FIELDVALUE valuestring="Start Trip" />
16
</FIELD>
17
</FEATURE>
18
<FEATURE featureid="2">
19
<FIELD name="SHAPE" type="-98" >
20
<FIELDVALUE>
21
<POINT x="-120.6" y="39.5" />
22
</FIELDVALUE>
23
</FIELD>
24
<FIELD name="Status" type="12">
25
<FIELDVALUE valuestring="Mid Trip" />
26
</FIELD>
27
</FEATURE>
28
<FEATURE featureid="3">
29
<FIELD name="SHAPE" type="-98" >
30
<FIELDVALUE>
31
<POINT x="-110.5" y="34.7" />
32
</FIELDVALUE>
33
</FIELD>
34
<FIELD name="Status" type="12">
35
<FIELDVALUE valuestring="End Trip" />
36
</FIELD>
37
</FEATURE>
38
<FEATURE featureid="4">
39
<FIELD name="SHAPE" type="-98" >
40
<FIELDVALUE>
41
<POINT x="-120.5" y="44.7" />
42
</FIELDVALUE>
43
</FIELD>
44
<FIELD name="Status" type="12">
45
<FIELDVALUE valuestring="End Trip" />
46
</FIELD>
47
</FEATURE>
48
</FEATURES>
49
</LAYER>
50
</REXML>
51
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 Source、MapResource、MapFunctionality、具体的地图数据 这几者之间的关系就非常容易理解了,这样就让一些特殊的数据格也可以在ADF中使用了大大提高了数据的灵活性。