加载中

Introduction

Mobile devices are becoming more and more connected to the internet. That's encourage developers to develop applications that uses this advantage. Web services are on the top of these apps. Nowadays, web services are a must known technology for every developer.

Requirements

As it is a Windows Phone Application, you will need to have Visual Studio for Windows Phone Express installed or Visual Studio 2010, which you can download them from

https://dev.windowsphone.com/en-us/downloadsdk and http://www.microsoft.com/visualstudio/en-us/try.

移动设备现在紧密的跟互联网结合,开发者应该利用这个优势来开发各种网络服务,今天我们介绍在 Windows Phone 上开发 Web 服务应用。

环境要求:

因为这是一个 Windows Phone 应用,你需要安装 Visual Studio for Windows Phone Express installed  或者 Visual Studio 2010,可通过下面地址下载:

About this application  

This app is gonna use Bing Maps to show the route between two points on the map and display it's lenght. As I will focus more on the web service, you could find Bing Maps and Bing Maps v2 helpful to start manipulating Bing Maps.Bing Maps in Windows Phone is simple article to start with.

Assuming that you have drop and dragged the Map control from the Toolbox to the main page and had inserted the following code related to the ApplicationBar:

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" Opacity="0.9">
        <shell:ApplicationBarIconButton IconUri="/Icons/plus.png" Text="Zoom In" Click="zoomIn_click"/>
        <shell:ApplicationBarIconButton IconUri="/Icons/minus.png" Text="Zoom out" Click="zoomOut_click"/>
        <shell:ApplicationBarIconButton IconUri="/Icons/A.png" Text="Aerial mode" Click="Aerial_click"/>
        <shell:ApplicationBarIconButton IconUri="/Icons/R.png" Text="Road mode" Click="Road_click"/>
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="Choose my position" Click="chooseMyPosition_click"/>
            <shell:ApplicationBarMenuItem Text="Locate Me" Click="locateMe_click"/>
            <shell:ApplicationBarMenuItem Text="Set Pushpin" Click="setPin_click"/>
            <shell:ApplicationBarMenuItem Text="Add Pushpin" Click="addPin_click"/>
            <shell:ApplicationBarMenuItem Text="Show Route" Click="showRoute_click"/>
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

Let's add these using statements to use the Maps features:

using Microsoft.Phone.Controls;
using Microsoft.Phone.Controls.Maps;
using System.Device.Location;

After that we wil be able to write this code:

//declaring the two Pushpins and the Polyline
Pushpin pin1 = new Pushpin();
Pushpin pin2 = new Pushpin();
MapPolyline poly = new MapPolyline(); 

Some initialization are required to display the Polyline in the Map:

//Initialization for polyline
poly.Locations = new LocationCollection();
poly.Opacity = 1.0;
poly.StrokeThickness = 3;
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Colors.Green;
poly.Stroke = mySolidColorBrush; 

Now, we will start using the web service. So, first of all lets right click on our project and click on Add Service Reference:


On the address field paste this reference to the route web service http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc/mex

and click "Go", then the services will appear in the Services field, to prove it's not a wrong reference.


When clicking the OK button, some files will be generated in your project. So now we can use that distributed service through its reference.

private void showRoute_click(object sender, EventArgs e)
{
    //creating the reference to the service
    ServiceReference1.RouteServiceClient proxy = 
      new ServiceReference1.RouteServiceClient("BasicHttpBinding_IRouteService");
    ServiceReference1.RouteRequest rr = new ServiceReference1.RouteRequest();
    
    //this service requires a key
    rr.Credentials = new ServiceReference1.Credentials();
    rr.Credentials.ApplicationId = 
        "Asa2x7ZzhYIHauji6TzIkcf3TIDznTgBaPKQehsyE4taOz19Mx4fP4lyihqbTj7D";
    rr.Options = new ServiceReference1.RouteOptions();
    rr.Options.RoutePathType = ServiceReference1.RoutePathType.Points;

    //declaring the two points
    ServiceReference1.Waypoint wp1 = new ServiceReference1.Waypoint();
    ServiceReference1.Waypoint wp2 = new ServiceReference1.Waypoint();

    //the first location is my location (from)
    wp1.Location = new ServiceReference1.Location();
    wp1.Location.Latitude = SharedInformation.myLatitude;
    wp1.Location.Longitude = SharedInformation.myLongitude;
    wp1.Description = "";
    //the second location is the destination (to)
    wp2.Location = new ServiceReference1.Location();
    wp2.Location.Latitude = SharedInformation.pinLat;
    wp2.Location.Longitude = SharedInformation.pinLong;
    wp2.Description = "";

    //setting the parameter to send
    rr.Waypoints = new System.Collections.ObjectModel.ObservableCollection<ServiceReference1.Waypoint>();
    rr.Waypoints.Add(wp1);
    rr.Waypoints.Add(wp2);

    //invoking the web service
    proxy.CalculateRouteAsync(rr);
    proxy.CalculateRouteCompleted += 
      new EventHandler<ServiceReference1.CalculateRouteCompletedEventArgs>(proxy_CalculateRouteCompleted);  
}

It's very important to know that the web service in Windows Phone is called in asynchronized way. That's why the expression "Async" is added to the end of the method's name. That's avoid the interface's thread to be blocked.

The IntelliSence could help you to show the different methods you can invoke from the web service with its full signature, as shown here:

The result returned by this web service is returned through the second parameter of theproxy_CalculateRouteCompleted method, which will be executed when there is a response from the service. This result is a list of points. Linked one to the next, they will draw the route we need to show using the polyline.

public void proxy_CalculateRouteCompleted(object obj, ServiceReference1.CalculateRouteCompletedEventArgs e)
{
    try
    {
        foreach (ServiceReference1.Location location in e.Result.Result.RoutePath.Points)
        {

            poly.Locations.Add(new GeoCoordinate(location.Latitude, location.Longitude));
        }

        //add the Polyline to the Map
        map1.Children.Add(poly);
        
        //display the distance between the two Pushpins
        pin2.Content = "It's " + e.Result.Result.Summary.Distance.ToString() + "Km far away!";
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}


The use of the try catch block is because the service may return some exceptions such as Point so far away from any road..

Some screenshots of the final app:

So that the result will be like this:

  


 hope you liked my article.

If you need any more information, please let me know.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



关于应用:

这个应用使用微软的 Bing 地图来显示两点之间的路线以及距离,我们更多的在讲述 Web 服务的使用,至于地图接口可参考 Bing MapsBing Maps v2 ,以及一些入门文章 Bing Maps in Windows Phone

假设你已经将地图控件从工具箱中拖到了主界面,并在 ApplicationBar 处插入如下代码:

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True" Opacity="0.9">
        <shell:ApplicationBarIconButton IconUri="/Icons/plus.png" Text="Zoom In" Click="zoomIn_click"/>
        <shell:ApplicationBarIconButton IconUri="/Icons/minus.png" Text="Zoom out" Click="zoomOut_click"/>
        <shell:ApplicationBarIconButton IconUri="/Icons/A.png" Text="Aerial mode" Click="Aerial_click"/>
        <shell:ApplicationBarIconButton IconUri="/Icons/R.png" Text="Road mode" Click="Road_click"/>
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="Choose my position" Click="chooseMyPosition_click"/>
            <shell:ApplicationBarMenuItem Text="Locate Me" Click="locateMe_click"/>
            <shell:ApplicationBarMenuItem Text="Set Pushpin" Click="setPin_click"/>
            <shell:ApplicationBarMenuItem Text="Add Pushpin" Click="addPin_click"/>
            <shell:ApplicationBarMenuItem Text="Show Route" Click="showRoute_click"/>
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

接下来使用如下代码来引入地图特性:

using Microsoft.Phone.Controls;
using Microsoft.Phone.Controls.Maps;
using System.Device.Location;

然后编写代码:

//declaring the two Pushpins and the Polyline
Pushpin pin1 = new Pushpin();
Pushpin pin2 = new Pushpin();
MapPolyline poly = new MapPolyline(); 

在地图上显示折线:

//Initialization for polyline
poly.Locations = new LocationCollection();
poly.Opacity = 1.0;
poly.StrokeThickness = 3;
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Colors.Green;
poly.Stroke = mySolidColorBrush; 


现在我们要开始使用 Web 服务,首先右击项目并选择 Add Service Reference:

在地址栏中粘贴下面 web 服务地址:

http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc/mex

点击 Go 后,该服务将出现在 Services 域中:

当点击 OK 按钮后,你项目里将生成一些文件,因此我们可以通过如下代码来使用这个服务:

private void showRoute_click(object sender, EventArgs e)
{
    //creating the reference to the service
    ServiceReference1.RouteServiceClient proxy = 
      new ServiceReference1.RouteServiceClient("BasicHttpBinding_IRouteService");
    ServiceReference1.RouteRequest rr = new ServiceReference1.RouteRequest();
    
    //this service requires a key
    rr.Credentials = new ServiceReference1.Credentials();
    rr.Credentials.ApplicationId = 
        "Asa2x7ZzhYIHauji6TzIkcf3TIDznTgBaPKQehsyE4taOz19Mx4fP4lyihqbTj7D";
    rr.Options = new ServiceReference1.RouteOptions();
    rr.Options.RoutePathType = ServiceReference1.RoutePathType.Points;

    //declaring the two points
    ServiceReference1.Waypoint wp1 = new ServiceReference1.Waypoint();
    ServiceReference1.Waypoint wp2 = new ServiceReference1.Waypoint();

    //the first location is my location (from)
    wp1.Location = new ServiceReference1.Location();
    wp1.Location.Latitude = SharedInformation.myLatitude;
    wp1.Location.Longitude = SharedInformation.myLongitude;
    wp1.Description = "";
    //the second location is the destination (to)
    wp2.Location = new ServiceReference1.Location();
    wp2.Location.Latitude = SharedInformation.pinLat;
    wp2.Location.Longitude = SharedInformation.pinLong;
    wp2.Description = "";

    //setting the parameter to send
    rr.Waypoints = new System.Collections.ObjectModel.ObservableCollection<ServiceReference1.Waypoint>();
    rr.Waypoints.Add(wp1);
    rr.Waypoints.Add(wp2);

    //invoking the web service
    proxy.CalculateRouteAsync(rr);
    proxy.CalculateRouteCompleted += 
      new EventHandler<ServiceReference1.CalculateRouteCompletedEventArgs>(proxy_CalculateRouteCompleted);  
}


这里非常重要的是 Windows Phone 是通过异步的方式来调用 Web 服务,这也是为什么方法名添加了 Async 表达式,这是为了让 UI 被操作堵塞。

IntelliSence 可帮你显示 Web 服务中提供的不同的方法,以及方法的参数:

来自 Web 服务的返回结果是通过第二个参数proxy_CalculateRouteCompleted来返回的,这个参数是一个方法,在调用 Web 服务有返回后这个方法将被调用,结果是一系列的点阵,我们可利用这些点阵来画线:

public void proxy_CalculateRouteCompleted(object obj, ServiceReference1.CalculateRouteCompletedEventArgs e)
{
    try
    {
        foreach (ServiceReference1.Location location in e.Result.Result.RoutePath.Points)
        {

            poly.Locations.Add(new GeoCoordinate(location.Latitude, location.Longitude));
        }

        //add the Polyline to the Map
        map1.Children.Add(poly);
        
        //display the distance between the two Pushpins
        pin2.Content = "It's " + e.Result.Result.Summary.Distance.ToString() + "Km far away!";
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}


使用 try-catch 的原因是调用服务可能发生异常,例如返回的点远离路径之类的。

下图是此 app 最终运行的截图:

绘制的路线图如下:

  

全文完,希望你喜欢这篇文章。

本文完整代码下载:http://www.oschina.net/code/snippet_12_12794

返回顶部
顶部