[Silverlight]利用Silverlight4的OOB(Out of Browser)結合WebBrowser控制項實作簡單的SL版GoogleMap

這週太無聊了,就來研究如何把Google Map結合在Silverlight呢

這週太無聊了,就來研究如何把Google Map結合在Silverlight呢

大家可以先看這個LiveDemo

這個Demo主要的功能為:

1.使用Out of Browser的方式呈現
2.使用Silverlight的WebBrowser控制項嵌入HTML Page(Google Map)
3.利用SL輸入Search Keyword字串,透由WebBrowser控制項以JavaScript方式呼叫HTML Page(Google Map)來呈現查詢結果

Code:

GoogleMap.xaml

<navigation:Page x:Class="F6.Demo.GoogleMap" 
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
           mc:Ignorable="d"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           d:DesignWidth="800" d:DesignHeight="600"
           Title="GoogleMap Page" Loaded="Page_Loaded" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
    <Grid x:Name="LayoutRoot">
        <WebBrowser Height="537" HorizontalAlignment="Left" Margin="0,63,0,0" Name="htmlMap" VerticalAlignment="Top" Width="800" Visibility="Collapsed" LoadCompleted="htmlMap_LoadCompleted" ScriptNotify="htmlMap_ScriptNotify" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="12,34,0,0" Name="txtKeyword" VerticalAlignment="Top" Width="412" />
        <Button Content="Search" Height="23" HorizontalAlignment="Left" Margin="430,34,0,0" Name="btnSearch" VerticalAlignment="Top" Width="75" Click="btnSearch_Click" />
        <sdk:Label Height="23" HorizontalAlignment="Left" Margin="592,34,0,0" Name="lblMsg" VerticalAlignment="Top" Width="109" />
        <Button Content="Install" Height="23" HorizontalAlignment="Left" Margin="349,0,0,0" Name="btnInstall" VerticalAlignment="Top" Width="75" Click="btnInstall_Click" />
        <Button Content="Exit" Height="23" HorizontalAlignment="Left" Margin="511,34,0,0" Name="btnExit" VerticalAlignment="Top" Width="75" Click="btnExit_Click" />
    </Grid>
</navigation:Page>

GoogleMap.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;

namespace F6.Demo
{
    public partial class GoogleMap : Page
    {
        public GoogleMap()
        {
            InitializeComponent();
            if (Application.Current.IsRunningOutOfBrowser)//判斷是否為OOB
            {
                this.btnInstall.Visibility = System.Windows.Visibility.Collapsed;
                this.txtKeyword.Visibility = System.Windows.Visibility.Visible;
                this.btnSearch.Visibility = System.Windows.Visibility.Visible;
                this.btnExit.Visibility = System.Windows.Visibility.Visible;
                this.lblMsg.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                this.txtKeyword.Visibility = System.Windows.Visibility.Collapsed;
                this.btnSearch.Visibility = System.Windows.Visibility.Collapsed;
                this.btnExit.Visibility = System.Windows.Visibility.Collapsed;
                this.lblMsg.Visibility = System.Windows.Visibility.Collapsed;
                if (Application.Current.InstallState == InstallState.NotInstalled)//判斷是否已經安裝過
                {
                    this.btnInstall.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    this.btnInstall.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            this.htmlMap.Navigate(new Uri(App.Current.Host.Source, "../map.htm"));
            App.Current.CheckAndDownloadUpdateCompleted += new CheckAndDownloadUpdateCompletedEventHandler(Current_CheckAndDownloadUpdateCompleted);
            App.Current.CheckAndDownloadUpdateAsync();//check update
        }

        void Current_CheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)
        {
            if (e.UpdateAvailable)
            {
                MessageBox.Show("Update received, please restart");
            }
        }

        private void htmlMap_LoadCompleted(object sender, NavigationEventArgs e)
        {
            this.htmlMap.Visibility = System.Windows.Visibility.Visible;
        }

        private void htmlMap_ScriptNotify(object sender, NotifyEventArgs e)
        {
            this.lblMsg.Content = e.Value;
        }

        private void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            this.htmlMap.InvokeScript("search", this.txtKeyword.Text);
        }

        private void btnInstall_Click(object sender, RoutedEventArgs e)
        {
            //自動Install
            Application.Current.Install();
        }

        private void btnExit_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.MainWindow.Close();//關閉Silverlight
        }
    }
}

map.htm

<!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>
    <title></title>
    <script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA6MZqTHlUV9uXPag5vBwoORTQGcTMH0-mpxA63vz4T9UKP6Ce4xSU1sNPIN6rAmk-iwwjJ1INKUh2Ag"
        type="text/javascript">
    </script>
    <style type="text/css">
        html, body
        {
            overflow: hidden;
        }
    </style>
    <script type="text/javascript">
        var geocoder;
        var map;

        var address = "高雄市火車站";

        // On page load, call this function
        function load() {
            // Create new map object
            map = new GMap2(document.getElementById("map"));

            // Create new geocoding object
            geocoder = new GClientGeocoder();

            // Retrieve location information, pass it to addToMap()
            geocoder.getLocations(address, addToMap);
        }

        function search(keyword) {
            geocoder.getLocations(keyword, addToMap);
        }

        // This function adds the point to the map

        function addToMap(response) {
            try {
                // Retrieve the object
                place = response.Placemark[0];

                // Retrieve the latitude and longitude
                point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);

                // Center the map on this point
                map.setCenter(point, 13);

                // Create a marker
                marker = new GMarker(point);

                // Add the marker to map
                map.addOverlay(marker);

                // Add address information to marker
                marker.openInfoWindowHtml(place.address);

                window.external.notify("Search completed");
            } catch (e) {
                window.external.notify("Not find.");
            }
        }

    </script>
</head>
<body onload="load()" onunload="GUnload()">
    <div id="map" style="width: 700px; height: 500px; border-right: black thin solid;
        border-top: black thin solid; border-left: black thin solid; border-bottom: black thin solid;">
    </div>
</body>
</html>


執行結果:

參考網址:
http://msdn.microsoft.com/en-us/library/dd550721(v=VS.96).aspx
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2009/11/18/silverlight-4-rough-notes-html-hosting-in-the-webbrowser-control.aspx
http://stackoverflow.com/questions/2677536/silverlight-4-oob-application-access-html-dom-of-the-page-in-webbrowser-control
http://www.dotblogs.com.tw/puma/archive/2008/03/06/1256.aspx