我们在前面的文章中讲WebLayout(MapGuide应用开发系列(九)—- MapGuide Studio准备地图之网页布局)的时候卖了个关子,提到可以通过程序更改WebLayout的xml表示来达到通过程序切换地图的目的。今天我们就来讲一下具体如何实现。

 

我们在前面的文章中讲WebLayout(MapGuide应用开发系列(九)—- MapGuide Studio准备地图之网页布局)的时候卖了个关子,提到可以通过程序更改WebLayout的xml表示来达到通过程序切换地图的目的。今天我们就来讲一下具体如何实现。

 

我在前面的文章中讲过资源的概念,WebLayout也是资源的一种,也是由XML定义的。而且我们还知道资源直接是有引用关系的,网页布局WebLayout中就引用了地图资源。MapGuide提供了一套完整的WebExtension API,其中对于资源的操作就要用的资源服务(ResourceService)。下面是我们将要用到的资源服务API的几个重要方法:

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); width: 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

//枚举知道资源ID下的所有资源
MgByteReader EnumerateResources(MgResourceIdentifier resource, int depth, string type);
//获取资源的内容 MgByteReader GetResourceContent(MgResourceIdentifier resource ); //为指定资源ID的资源设置资源内容和资源头,可用来更新资源 void SetResource(MgResourceIdentifier resource, MgByteReader content, MgByteReader header);

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); width: 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

 

然后还是重温一下WebLayout的XML定义中关于Map的部分,了解我们在使用程序切换地图的时候应该朝哪部分下手:)

<?xml version="1.0" encoding="utf-8"?>
<WebLayout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="WebLayout-1.0.0.xsd">
  <Title>Sheboygan Map</Title>
  <Map>
    <ResourceId>Library://Samples/Sheboygan/MapsTiled/Sheboygan.MapDefinition</ResourceId>
    <HyperlinkTarget>TaskPane</HyperlinkTarget>
  </Map>

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); width: 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

 

好了准备就绪,开始动手了. 我们想要在任务栏中添加一个按钮,点击这个按钮引发到一个页面,在这个页面加载的时候枚举MapGuide 服务器上所有可用的MapDefinition 添加到一个下拉框中的,然后用户可以选择任意一个地图,实现地图的自动切换.这就是我们要做的工作.

第一步, 要在MapGuide Studio中添加一个Invoke URL的命令,并添加到任务栏Taskbar或者工具栏ToolBar中. 定义这个命令将引发的URL为http://www.cnblogs.com/SwitchMaps/SwitchMapsUI.aspx, 这里是相当MapGuide view的相对路径.并且注意到下面Display result in this target interface我们选择的是 Task Pane,显示在任务面板中.你也可以在这里指定其他的frame名从而显示到不同的框架中.

image image

 

 

然后我们打开Visual Studio 2005或者VS 2008, 在本地IIS上创建一个Web站点, http://localhost/SwitchMaps/, 创建成功后在IIS中应该是这样的,注意SwitchMaps虚拟目录和MapGuide2010虚拟目录的相对位置,并结合我们上面的URL设置http://www.cnblogs.com/SwitchMaps/SwitchMapsUI.aspx来对照理解这个URL的写法。

image

要在Visual Studio里开发基于MapGuide的应用程序,当然要添加MapGuide相关dll的引用,我们可以创建一个bin目录,然后把C:\Program Files\Autodesk\MapGuideEnterprise2010\WebServerExtensions\www\mapviewernet\bin下所有的dll拷贝到应用程序的bin目录下。

首页中加入我们的MapGuide Ajax Viewer,如下:

<%@ Page Language="C#" %>
<%@ Import Namespace="OSGeo.MapGuide" %>


<%
    Utility utility = new Utility();
String webLayout = "Library://Samples/Sheboygan/Layouts/SheboyganAsp.WebLayout";
Session["InitWebLayout"] = webLayout; // for convenience, I put the weblayer into Session
String sessionId = "";

try { utility.InitializeWebTier(Request); MgUserInformation userInfo = new MgUserInformation("Anonymous", "");
MgSite site = new MgSite();

site.Open(userInfo);

sessionId = site.CreateSession();
}
catch (MgException mge)
{
Response.Write(mge.GetMessage());
Response.Write(mge.GetDetails());
}
finally { } %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title>Viewer Sample Application</title> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/> <meta http-equiv="content-script-type" content="text/javascript" /> <meta http-equiv="content-style-type" content="text/css" /> </head> <frameset rows="0,*" border="0" framespacing="0"> <frame /> <frame src="/mapguide2010/mapviewernet/ajaxviewer.aspx?SESSION=<%= sessionId %>&WEBLAYOUT=<%= webLayout %>" name="ViewerFrame" id = "ViewerFrame" /> </frameset> <script> </script> </html>

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); width: 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

 

然后我们创建一个页面SwitchMapsUI.aspx.这个页面的实现才是我们今天要讲述的重点。为了演示,界面设计很简单,就一个ComboBox和一个Button。我们看一下重点代码:

 

这是获取指定资源目录下的所有地图资源:

    /// <summary>
    ///  enumberate all the map definitions in the 
    /// </summary>
    /// <param name="resId"></param>
    /// <returns></returns>
    public Dictionary<string, string> GetAllMaps(MgResourceIdentifier resId)
{
Dictionary<string, string> mapList = new Dictionary<string, string>();

MgResourceService resSvc = siteConnection.CreateService(MgServiceType.ResourceService) as MgResourceService;

// Get all map def resources MgByteReader byteRdr = resSvc.EnumerateResources(resId, -1, MgResourceType.MapDefinition); //Convert to string String MapResStr = byteRdr.ToString(); //Load into XML document so we can parse and get the names of the maps XmlDocument doc = new XmlDocument();
doc.LoadXml(MapResStr);

//let\'s extract the map names and list them XmlNodeList MapResIdNodeList; XmlElement root = doc.DocumentElement; MapResIdNodeList = root.SelectNodes("//ResourceId");
int nRes = MapResIdNodeList.Count;

for (int i = 0; i < nRes; i++)
{
XmlNode MapResIdNode = MapResIdNodeList.Item(i);
String MapRes = MapResIdNode.InnerText;
int index1 = MapRes.LastIndexOf(\'/\') + 1;
int index2 = MapRes.IndexOf("MapDefinition") - 2;
int length = index2 - index1 + 1;
string mapName = MapRes.Substring(index1, length);
if (!mapList.ContainsKey(mapName))
{
mapList.Add(mapName, MapRes);
}

}

return mapList;


}

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); width: 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

 

 

下面是通过资源服务API,首先读取出WebLayout资源的xml表示,通过在DOM中查找替换<ResourceId>节点的内容,然后在更新回到一个会话资源中,并返回这个会话资源的资源ID。 为什么要更新到一个会话资源中呢?我们开发的是WebGIS系统,你肯定不希望一个用户在调用你这个功能切换地图时,把所有在使用这个地图服务的用户的地图全部切换了吧,那样用户是不是会觉得很恐怖:)

 

    /// <summary>
    /// Edit the weblayout resource content to change map
    /// </summary>
    /// <param name="webLayout">the resourece id of weblayout</param>
    /// <param name="sessionId">current session string</param>
    /// <param name="mapDefResourceId">resource id of map definition</param>
    /// <returns></returns>
    public string SwitchMapsInWebLayout(string webLayout, string sessionId, string mapDefResourceId)
{
MgResourceIdentifier layoutResId = new MgResourceIdentifier(webLayout);
MgResourceService resSvc = siteConnection.CreateService(MgServiceType.ResourceService) as MgResourceService;
//the resource content of WebLayout MgByteReader reader = resSvc.GetResourceContent(layoutResId); string layoutXml = reader.ToString();

//Edit the map resource in XmlDocument in DOM XmlDocument doc = new XmlDocument();

doc.LoadXml(layoutXml);
XmlNode nodeCenterX = doc.GetElementsByTagName("ResourceId").Item(0);
nodeCenterX.InnerText = mapDefResourceId;

MgByteSource byteSource = ByteSourceFromXMLDoc(doc);
string sessionLayoutName = layoutResId.GetName();
string sessionLayout = "Session:" + sessionId + @"//" + sessionLayoutName + ".WebLayout";
MgResourceIdentifier sessionLayoutResId = new MgResourceIdentifier(sessionLayout);

//update back to a session weblayout resSvc.SetResource(sessionLayoutResId, byteSource.GetReader(), null);

return sessionLayout;


}

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); width: 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

 

最后为了让更改在界面上起作用,真正切换地图,我们需要更新MapGuide Viewer的WebLayout参数,并使之刷新从而重新加载更改过的地图:

protected void Button1_Click(object sender, EventArgs e)
{
Response.Write(ddlMaps.SelectedValue);

Utility utility = new Utility();
string session = Session["MgSession"].ToString();
utility.ConnectToServer(session);

string webLayout = Session["InitWebLayout"].ToString();
string sessionLayout = utility.SwitchMapsInWebLayout(webLayout, session, ddlMaps.SelectedValue);

string viewerPath = string.Format(viewerPathSchema, session, sessionLayout);

string code = "<script>parent.parent.parent.frames(\'ViewerFrame\').location.href = \'" + viewerPath + "\'; </script>";
Response.Write(code);

}

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); width: 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

 

好了,大功告成,我们看一下效果吧:

初始地图,页面加载枚举出所有可用地图:

image

 

地图切换后,注意到我们自定义的命令SwitchMap还在哦 :)

image

 

好了,通过这个例子,大家应该能知道如果运用ResourceService对资源进行相关修改更新的操作。以后的应用就看你的想象力了 :) Go MapGuiding !

完整代码下载:  SwitchMaps.zip

有任何意见建议欢迎评论或到MGDN论坛讨论。

转载请注明出处及作者 峻祁连 Daniel Du 杜长宇

版权声明:本文为junqilian原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/junqilian/archive/2009/11/14/1603189.html