Hi,
There is no direct support for GML in the ArcGIS Runtime SDK for WPF. However, if this is a key requirement for you, you could consider writing a custom layer. An example of this (the KML layer implementation) can be found in the ESRI.ArcGIS.Client.Toolkit.Datasources source code available on codeplex: http://esrisilverlight.codeplex.com/releases/view/80697. Download the source code then look in "ESRIToolkitSource_v2.4.zip\WPF\ESRI.ArcGIS.Client.Toolkit.DataSources\Kml".
Cheers
Mike
public static string latLongToXML (decimal lat, decimal Long)
{
StringBuilder GeoXMLStr = new StringBuilder();
XmlWriterSettings xWSettings = new XmlWriterSettings();
xWSettings.OmitXmlDeclaration = true;
XmlWriter xW = XmlWriter.Create(GeoXMLStr, xWSettings);
using (xW)
{
xW.WriteStartElement("Point", "http://www.opengis.net/gml");
xW.WriteStartElement("pos");
xW.WriteRaw(lat.ToString() + " " + Long.ToString());
xW.WriteEndElement();
xW.WriteEndElement();
xW.Flush();
xW.Close();
}
return GeoXMLStr.ToString();
Imports System
Imports System.Data
Imports System.Xml
Imports System.Text
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.IO
Imports ESRI.ArcGISExplorer
Imports ESRI.ArcGISExplorer.Application
Imports ESRI.ArcGISExplorer.Geometry
Imports ESRI.ArcGISExplorer.Mapping
Imports ESRI.ArcGISExplorer.Data
Imports ESRI.ArcGISExplorer.Threading
Imports Microsoft.VisualBasic
Public Class GML
Public Type As String = Nothing
Friend WithEvents InciTableAdapter As New Inci.WRMSDataSetTableAdapters.InciTableAdapter
Friend WithEvents WRMSDataSet As New Inci.WRMSDataSet
Friend WithEvents GMLRtrnDataTable As New DataTable
Private disp As MapDisplay = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay
Public Sub PerimGet(ByVal InciName As String)
Me.InciTableAdapter.FillByInciNumber(WRMSDataSet.Inci, InciName)
For Each InfoRow In Me.WRMSDataSet.Inci
InfoRow("GML").ToString()
Next InfoRow
End Sub
Public Function XMLToGeom(ByVal XMLGeo As String)
Dim Perim As Polygon = New Polygon()
Using XMLRead As XmlReader = XmlReader.Create(New StringReader(XMLGeo))
XMLRead.ReadToFollowing("posList")
Dim LatLongStrArr() As String = (XMLRead.ReadElementContentAsString()).Split(" ")
For I = LatLongStrArr.Length - 1 To 0 Step -2
Perim.AddPoint(ESRI.ArcGISExplorer.Geometry.Point.CreateFromLatitudeLongitude(CDbl(LatLongStrArr(I - 1).ToString), CDbl(LatLongStrArr(I).ToString)))
Next I
Perim.Close()
Return Perim
End
Using resource As New Object
End Using
End Function
Public Sub CreateNwInci(ByVal InciName As String, ByVal InciNumber As String, ByVal InciType As String, ByVal GeomAsXML As String)
'Inserts Incident data into the WRMS Datatables
Try
Me.InciTableAdapter.USP_CrtNwInci(InciName, InciNumber, InciType, GeomAsXML, Now)
GetInci(InciNumber)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Public Function GeomToXML(ByVal GObj As Geometry)
Dim GeoPoly As Polygon = GObj
Dim GeoXMLStr As New StringBuilder
Dim XwSettings As XmlWriterSettings = New XmlWriterSettings()
XwSettings.OmitXmlDeclaration = True
Using Xw As XmlWriter = XmlWriter.Create(GeoXMLStr, XwSettings)
Xw.WriteStartElement("Polygon", "http://www.opengis.net/gml")
Xw.WriteStartElement("exterior")
Xw.WriteStartElement("LinearRing")
Xw.WriteStartElement("posList")
For Pt = GeoPoly.PointCount - 1 To 0 Step -1
Xw.WriteRaw(GeoPoly.GetPoint(Pt).GetLatitude.ToString("####.000000") + " " + GeoPoly.GetPoint(Pt).GetLongitude.ToString("####.000000") + " ")
Next Pt
Xw.WriteEndElement()
Xw.WriteEndElement()
Xw.WriteEndElement()
Xw.WriteEndElement()
Xw.Flush()
Xw.Close()
End Using
Return GeoXMLStr.ToString
End Function
Public Sub GetInci(ByVal InciNumber As String)
GMLRtrnDataTable = Me.InciTableAdapter.GetDataByInciNumber(InciNumber)
For Each Row As DataRow In GMLRtrnDataTable.Rows
Dim PerimNt As New Note(Row("Inci_Name").ToString(), _
XMLToGeom(Row("GML").ToString()), _
Symbol.Fill.Solid.Red)
PerimNt.Popup.Content = "Acres: " + Row("Inci_Acreage").ToString()
disp.Map.ChildItems.Add(PerimNt)
Next Row
End Sub
End Class
using WRMS.Framework.Utilities;
using System.ComponentModel;
using System.Windows.Input;
using WRMS.Framework.Commands;
using Microsoft.Win32;
using System.IO;
using System.Xml;
using System.Net;
using Ionic.Zip;
using System;
using System.Windows.Documents;
using System.Collections.Generic;
using System.Xml.Linq;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;
using System.Text.RegularExpressions;
using AffCore;
namespace WRMS.Framework.ViewModels
{
class AffVM : MapHelper, INotifyPropertyChanged
{
GraphicsLayer graphicsLayer = _map.Layers["affResourcesGraphicsLayer"] as GraphicsLayer;
OpenFileDialog ofd;
XmlDocument affFileObj = new XmlDocument();
string resourceUrl;
private string _path;
public string path
{
get { return _path; }
set
{
if (_path != value)
{
_path = value;
onPropertyChanged("url");
}
}
}
private string _bytesReceivedDisp;
public string bytesReceivedDisp
{
get { return _bytesReceivedDisp; }
set
{
if (_bytesReceivedDisp!=value)
{
_bytesReceivedDisp = value;
onPropertyChanged("bytesReceivedDisp");
}
}
}
private string _totalBytesDisp;
public string totalBytesDisp
{
get { return _totalBytesDisp; }
set
{
if (_totalBytesDisp!=value)
{
_totalBytesDisp = value;
onPropertyChanged("totalBytesDisp");
}
}
}
private double _bytesReceived;
public double bytesReceived
{
get { return _bytesReceived; }
set
{
if (_bytesReceived != value)
{
_bytesReceived = value;
onPropertyChanged("bytesReceived");
}
}
}
private double _totalBytes = 100;
public double totalBytes
{
get { return _totalBytes; }
set
{
if (_totalBytes != value)
{
_totalBytes = value;
onPropertyChanged("totalBytes");
}
}
}
private string _status;
public string status
{
get { return _status; }
set
{
if (_status != value)
{
_status = value;
onPropertyChanged("status");
}
}
}
private bool _isDisplayed;
public bool isDisplayed
{
get { return _isDisplayed; }
set
{
if (_isDisplayed!=value)
{
_isDisplayed = value;
onPropertyChanged("isDisplayed");
}
}
}
private List<Graphic> _airResourceGraphics;
public List<Graphic> airResourceGraphics
{
get { return _airResourceGraphics; }
set
{
if (_airResourceGraphics!=value)
{
_airResourceGraphics = value;
onPropertyChanged("airResourceGraphics");
}
}
}
private string _returnMessage;
public string returnMessage
{
get { return _returnMessage; }
set
{
if (_returnMessage != value)
{
_returnMessage = value;
onPropertyChanged("returnMessage");
}
}
}
private bool _displayIsChecked;
public bool displayIsChecked
{
get { return _displayIsChecked; }
set
{
if (_displayIsChecked != value)
{
_displayIsChecked = value;
onPropertyChanged("displayIsChecked");
}
}
}
private string _tmpResourceKml;
private string _tmpKmz;
private const double _maxX = -126.58;
private const double _minX = -114.21;
private const double _maxY = 48.18;
private const double _minY = 39.96;
private double _latitude;
private double _longitude;
public ICommand addKmlAffLayerCommand { get { return new AddKmlAffLayerCommand(this); } }
public ICommand toggleDisplayAff { get { return new ToggleDisplayAffCommand(this); } }
public void addAff()
{
returnMessage = "";
ofd = new OpenFileDialog();
ofd.DefaultExt = ".kml";
ofd.Filter = "AFF KML File (*.KML)|*.kml|AFF KMZ File (*.kmz)|*.kmz";
ofd.ShowDialog();
if (ofd.FileName!="")
{
path = ofd.FileName;
status = "Loading";
affFile(path);
}
}
private void affFile(string kmlFilePath)
{
affFileObj.Load(kmlFilePath);
using (XmlReader reader = XmlReader.Create(affFileObj.BaseURI))
{
reader.ReadToFollowing("Url");
XmlReader urlXml= reader.ReadSubtree();
urlXml.ReadToFollowing("href");
resourceUrl = urlXml.ReadString();
}
_tmpKmz = Path.GetTempPath().ToString() + "resource.zip";
_tmpResourceKml = Path.GetTempPath().ToString() + "resource.kml";
WebClient webDownloader = new WebClient();
webDownloader.DownloadFileCompleted += (sender, e) =>
{
using (ZipFile kmz = ZipFile.Read(_tmpKmz))
foreach (ZipEntry item in kmz)
item.Extract(_tmpResourceKml,ExtractExistingFileAction.OverwriteSilently);
status = "refreshing";
parseKmlResources();
};
webDownloader.DownloadProgressChanged += (sender, e) =>
{
bytesReceivedDisp = e.BytesReceived.ToString() + "kb/";
totalBytesDisp = e.TotalBytesToReceive.ToString() + "kb";
bytesReceived = Convert.ToDouble(e.BytesReceived);
totalBytes = Convert.ToDouble(e.TotalBytesToReceive);
};
webDownloader.DownloadFileAsync(new System.Uri(resourceUrl), _tmpKmz);
}
private void parseKmlResources()
{
List<Graphic> graphics = new List<Graphic>();
var resourceXml = XDocument.Load(_tmpResourceKml + "/resource.kml");
string xmlNs = "{" + resourceXml.Root.Name.Namespace.ToString() + "}";
foreach (var placemark in resourceXml.Descendants(xmlNs + "Placemark"))
{
foreach (var coordinates in placemark.Descendants(xmlNs + "Point"))
{
string[] coordinateCollection = coordinates.Element(xmlNs + "coordinates").Value.ToString().Split(new char[] { ',' });
_longitude = Convert.ToDouble(coordinateCollection[0]);
_latitude = Convert.ToDouble(coordinateCollection[1]);
}
if (_latitude < _maxY && _latitude > _minY)
{
if (_longitude > _maxX && _longitude < _minX)
{
MobileResource affResource = new MobileResource(placemark.Value.ToString());
Graphic airResourceGraphic = new Graphic() { Geometry = new MapPoint(_longitude, _latitude, new SpatialReference(4326)) };
airResourceGraphic.Attributes.Add("Callsign", affResource.callsign);
graphics.Add(airResourceGraphic);
}
}
}
airResourceGraphics = graphics;
graphicsLayer.GraphicsSource = airResourceGraphics;
//this is where the if statement will be if the Display button is checked
File.Delete(_tmpKmz);
affFile(path);
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void onPropertyChanged(string propertyName)
{
try
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
catch (Exception)
{
//implement a new type of exception to be honest I really don't because when the style template is reloaded it will still populate
}
}
#endregion
}
}