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的配置文件用来给我们的工程用,具体的内容和说明如下:
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文件,具体的代码和说明如下:
namespace REXMLDataSource2
{3
public class GISDataSource : IGISDataSource4
{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 Name53
{54
get { return name; }55
set { name = value; }56
}57

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

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

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

87
//GISDataSource的Resources,IGISDataSource接口必须实现的成员88
public GISResourceCollection Resources89
{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 State97
{98
get99
{100
return m_state;101
}102
}103

104
//GISDataSource的是否初始化标识,IGISDataSource接口必须实现的成员105
public bool Initialized106
{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

namespace REXMLDataSource2
{3
//MapResource实现IMapResource接口,而IMapResource实现了IGISResource接口,所以MapResource必须实现IMapResource和IGISResource的必要成员4
public class MapResource : IMapResource5
{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 Graphics16
{17
get { return graphics; }18
}19

20
private IMapInformation mapInformation = null;21
private DisplaySettings displaySettings = null;22

23
//IMapResource接口必须实现的成员,Map信息24
public IMapInformation MapInformation25
{26
get { return mapInformation; }27
set { mapInformation = value; }28
}29

30
//IMapResource接口必须实现的成员,地图显示设置31
public DisplaySettings DisplaySettings32
{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 ValidationTimeout47
{48
get { return validationtimeout; }49
set { validationtimeout = value; }50
}51

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

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

66
//IGISResource接口必须实现的成员,Resource的Data Source67
public IGISDataSource DataSource68
{69
get { return dataSource; }70
set { dataSource = value; }71
}72

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

80
//IGISResource接口必须实现的成员,判定是否支持各类的Functionality81
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
else96
{97
return false;98
} 99
}100

101
//IGISResource接口必须实现的成员,创建各种Functionality102
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.cs108
gisfunctionality = new MapFunctionality(functionalityName, this);109
}110
else if (functionalityType == typeof(ESRI.ArcGIS.ADF.Web.DataSources.IMapTocFunctionality))111
{112
//MapTocFunctionality,具体见MapTocFunctionality.cs113
gisfunctionality = new MapTocFunctionality(functionalityName, this);114
}115
else if (functionalityType == typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality))116
{117
//QueryFunctionality,具体见QueryFunctionality.cs118
gisfunctionality = new QueryFunctionality(functionalityName, this);119
}120
else121
{122
throw new ArgumentException("functionalityType not supported");123
}124
return gisfunctionality;125
}126

127
//IGISResource接口必须实现的成员,是否初始化128
public bool Initialized129
{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.cs156
mapInformation = new MapInformation(graphics);157
if (DisplaySettings != null)158
{159
//设置GraphicsDataSet的ImageDescriptor160
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中的key192
private string key193
{194
get195
{196
string tmp = this.GetType().ToString() + ":" + name;197
return (tmp);198
}199
}200

201
private void ProcessREXML(string dataSourceConfig)202
{203
try204
{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 FeatureGraphicsLayer219
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 FeatureGraphicsLayer228
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
//获取FEATURES294
XmlNode featuresNode = layerNode.SelectSingleNode("FEATURES");295
XmlNodeList featureNodes = featuresNode.SelectNodes("FEATURE");296

297
//获取SHAPE的字段属性建立GraphicElement298
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就建立DataRow306
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添加到GraphicsDataSet350
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数据内容如下:
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中使用了大大提高了数据的灵活性。



浙公网安备 33010602011771号