ASP.NET AJAX Advance Tips & Tricks (6) AJAX Control Toolkit 与 Virtual Earth的兼容问题
前言:
Virtual Earth作为微软的地图服务,在技术和实用性上与Google Map有的一拼,某些方面还比Google Map做的要好,用的人也越来越多了。但由于其JavaScript的高度封装特性,最近遇到了不少Virtual Earth与ASP.NET AJAX不兼容的情况。案例既多又复杂,本篇通过一个有代表性的例子来讨论两者的兼容,希望能帮助遇到此麻烦的开发者解决问题。
问题重现:
下面的代码将一个Virtual Earth地图放在一个AJAX Control Toolkit 的Tab Panel里:
<%@ Page Language="C#" %>
<!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>Virtual Earth Test</title>
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
<script type="text/javascript">
var map = null;
function GetMap() {
map = new VEMap('myMap');
map.LoadMap();
}
function DoZoomIn(c) {
map.ZoomIn();
}
function DoZoomOut() {
map.ZoomOut();
}
function DoCenterZoom() {
var lat = document.getElementById('txtMapLat').value;
var lon = document.getElementById('txtMapLon').value;
var zoom = document.getElementById('zoomLevel').value;
map.SetCenterAndZoom(new VELatLong(lat, lon), zoom);
}
</script>
</head>
<body onload="GetMap();">
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<ajaxToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0" >
<ajaxToolkit:TabPanel runat="server" HeaderText="Pictures" ID="TabPanel1">
<ContentTemplate>
Pictures
</ContentTemplate>
</ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanel runat="server" HeaderText="Location" ID="TabPanel2">
<ContentTemplate>
<div id='myMap' style="position:relative; width:350px; height:300px;"></div>
<div>Latitude:<input id='txtMapLat' style='width: 30px' type='text' value='45' /></div>
<div>Longtidude:<input id='txtMapLon' style='width: 30px' type='text' value='-120' /></div>
<div>
Zoom level:<input id='zoomLevel' type='text' style='width:15px;' value='5' />
<input type='button' value='Set center & zoom' onclick='DoCenterZoom();' />
</div>
</ContentTemplate>
</ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>
</div>
</form>
</body>
</html>
<!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>Virtual Earth Test</title>
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
<script type="text/javascript">
var map = null;
function GetMap() {
map = new VEMap('myMap');
map.LoadMap();
}
function DoZoomIn(c) {
map.ZoomIn();
}
function DoZoomOut() {
map.ZoomOut();
}
function DoCenterZoom() {
var lat = document.getElementById('txtMapLat').value;
var lon = document.getElementById('txtMapLon').value;
var zoom = document.getElementById('zoomLevel').value;
map.SetCenterAndZoom(new VELatLong(lat, lon), zoom);
}
</script>
</head>
<body onload="GetMap();">
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<ajaxToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0" >
<ajaxToolkit:TabPanel runat="server" HeaderText="Pictures" ID="TabPanel1">
<ContentTemplate>
Pictures
</ContentTemplate>
</ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanel runat="server" HeaderText="Location" ID="TabPanel2">
<ContentTemplate>
<div id='myMap' style="position:relative; width:350px; height:300px;"></div>
<div>Latitude:<input id='txtMapLat' style='width: 30px' type='text' value='45' /></div>
<div>Longtidude:<input id='txtMapLon' style='width: 30px' type='text' value='-120' /></div>
<div>
Zoom level:<input id='zoomLevel' type='text' style='width:15px;' value='5' />
<input type='button' value='Set center & zoom' onclick='DoCenterZoom();' />
</div>
</ContentTemplate>
</ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>
</div>
</form>
</body>
</html>
结果,我们可以发现,地图出现了问题,没有被正确载入:
解决方案:
在TabContainer 的OnClientActiveTabChanged事件中重新调用GetMap方法生成地图,可以解决此问题:
<ajaxToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0" OnClientActiveTabChanged="GetMap">
这次工作正常:
整页代码如下:
<%@ Page Language="C#" %>
<!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>Virtual Earth Test</title>
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
<script type="text/javascript">
var map = null;
function GetMap() {
map = new VEMap('myMap');
map.LoadMap();
}
function DoZoomIn(c) {
map.ZoomIn();
}
function DoZoomOut() {
map.ZoomOut();
}
function DoCenterZoom() {
var lat = document.getElementById('txtMapLat').value;
var lon = document.getElementById('txtMapLon').value;
var zoom = document.getElementById('zoomLevel').value;
map.SetCenterAndZoom(new VELatLong(lat, lon), zoom);
}
</script>
</head>
<body onload="GetMap();">
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<ajaxToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0" OnClientActiveTabChanged="GetMap">
<ajaxToolkit:TabPanel runat="server" HeaderText="Pictures" ID="TabPanel1">
<ContentTemplate>
Pictures
</ContentTemplate>
</ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanel runat="server" HeaderText="Location" ID="TabPanel2">
<ContentTemplate>
<div id='myMap' style="position: relative; width: 350px; height: 300px;">
</div>
<div>
Latitude:<input id='txtMapLat' style='width: 30px' type='text' value='45' /></div>
<div>
Longtidude:<input id='txtMapLon' style='width: 30px' type='text' value='-120' /></div>
<div>
Zoom level:<input id='zoomLevel' type='text' style='width: 15px;' value='5' />
<input type='button' value='Set center & zoom' onclick='DoCenterZoom();' />
</div>
</ContentTemplate>
</ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>
</div>
</form>
</body>
</html>
<!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>Virtual Earth Test</title>
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
<script type="text/javascript">
var map = null;
function GetMap() {
map = new VEMap('myMap');
map.LoadMap();
}
function DoZoomIn(c) {
map.ZoomIn();
}
function DoZoomOut() {
map.ZoomOut();
}
function DoCenterZoom() {
var lat = document.getElementById('txtMapLat').value;
var lon = document.getElementById('txtMapLon').value;
var zoom = document.getElementById('zoomLevel').value;
map.SetCenterAndZoom(new VELatLong(lat, lon), zoom);
}
</script>
</head>
<body onload="GetMap();">
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<ajaxToolkit:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0" OnClientActiveTabChanged="GetMap">
<ajaxToolkit:TabPanel runat="server" HeaderText="Pictures" ID="TabPanel1">
<ContentTemplate>
Pictures
</ContentTemplate>
</ajaxToolkit:TabPanel>
<ajaxToolkit:TabPanel runat="server" HeaderText="Location" ID="TabPanel2">
<ContentTemplate>
<div id='myMap' style="position: relative; width: 350px; height: 300px;">
</div>
<div>
Latitude:<input id='txtMapLat' style='width: 30px' type='text' value='45' /></div>
<div>
Longtidude:<input id='txtMapLon' style='width: 30px' type='text' value='-120' /></div>
<div>
Zoom level:<input id='zoomLevel' type='text' style='width: 15px;' value='5' />
<input type='button' value='Set center & zoom' onclick='DoCenterZoom();' />
</div>
</ContentTemplate>
</ajaxToolkit:TabPanel>
</ajaxToolkit:TabContainer>
</div>
</form>
</body>
</html>
微软经常弄出自己的产品之间不兼容的囧事,不过也难为微软了,有着全球最庞大的客户队伍,产品涉及面极广,并且每个产品都尽量做到极高程度的封装,实在不易。