Windows Phone 7 网络编程之天气预报应用
天气预报应用是通过异步调用Google天气api(http://www.google.com/ig/api?weather=城市拼音),对其进行xml的数据解析,将其数据简单的展现出在Windows Phone 7的客户端上。
首页的城市数据绑定类,以及预设好的城市列表
City.cs
using System.ComponentModel;
namespace WeatherForecast
{
/// <summary>
/// 城市绑定类
/// </summary>
public class City : INotifyPropertyChanged
{
private string cityPinyin;//城市拼音
private string province;//省份
private string cityName;//城市名称
public string CityPinyin
{
get
{
return cityPinyin;
}
set
{
if (value != cityPinyin)
{
cityPinyin = value;
NotifyPropertyChanged("CityPinyin");
}
}
}
public string Province
{
get
{
return province;
}
set
{
if (value != province)
{
province = value;
NotifyPropertyChanged("Province");
}
}
}
public string CityName
{
get
{
return cityName;
}
set
{
if (value != cityName)
{
cityName = value;
NotifyPropertyChanged("CityName");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// 构造city类
/// </summary>
public City(string cityPinyin, string province, string cityName)
{
CityPinyin = cityPinyin;
Province = province;
CityName = cityName;
}
/// <summary>
///用于绑定属性值改变触发的事件,动态改变
/// </summary>
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
Cities.cs
using System.Collections.ObjectModel;
namespace WeatherForecast
{
/// <summary>
/// 继承 ObservableCollection<City>用户数据绑定
/// </summary>
public class Cities : ObservableCollection<City>
{
public Cities() { }
/// <summary>
/// 设置默认的绑定城市 利用App类里面定义的静态变量cityList
/// </summary>
public void LoadDefaultData()
{
App.cityList.Add(new City("Shenzhen", "广东省", "深圳市"));
App.cityList.Add(new City("Beijing", "北京市", "北京市"));
App.cityList.Add(new City("Shanghai", "上海市", "上海市"));
App.cityList.Add(new City("Guangzhou", "广东省", "广州市"));
App.cityList.Add(new City("Yangjiang", "广东省", "阳江市"));
}
}
}
对首页城市列表的绑定需要在app程序启动类里面赋值
App.xaml.cs需要添加获取城市列表的代码
public static Cities cityList;//绑定的城市列表
……
private void Application_Launching(object sender, LaunchingEventArgs e)
{
// 创建城市列表
if ( cityList==null)
{
cityList = new Cities();
cityList.LoadDefaultData();
}
}
首页的界面设计代码
<phone:PhoneApplicationPage
x:Class="WeatherForecast.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="PageTitle" Text="天气预报" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox Height="646" HorizontalAlignment="Left" Margin="6,0,0,0" Name="CityList" VerticalAlignment="Top" Width="474" SelectionChanged="CityList_SelectionChanged">
<ListBox.ItemTemplate><!--数据绑定-->
<DataTemplate>
<StackPanel x:Name="stackPanelCityList" Orientation="Vertical" >
<TextBlock HorizontalAlignment="Left" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="40" Text="{Binding CityPinyin}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Margin="0,0,10,0" FontSize="25" Text="省份:" Foreground="LightBlue"/>
<TextBlock Margin="0,0,10,0" FontSize="25" Text="{Binding Province}" Foreground="{StaticResource PhoneForegroundBrush}"/>
<TextBlock Margin="0,0,10,0" FontSize="25" Text="城市:" Foreground="LightBlue"/>
<TextBlock Margin="0,0,10,0" FontSize="25" Text="{Binding CityName}" Foreground="{StaticResource PhoneForegroundBrush}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
using System;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;
namespace WeatherForecast
{
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
CityList.ItemsSource = App.cityList;//绑定城市列表
}
/// <summary>
/// 获取天气预报事件
/// </summary>
private void CityList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// 如果列被选中
if (CityList.SelectedIndex != -1)
{
City curCity = (City)CityList.SelectedItem;//获取当前选中的城市的绑定的类
this.NavigationService.Navigate(new Uri("/ForecastPage.xaml?City=" +
curCity.CityPinyin, UriKind.Relative));//跳转向ForecastPage.xaml 并传递参数CityPinyin 接口要用到城市的拼音
}
}
/// <summary>
/// 跳转到ForecastPage.xaml页面前执行该事件
/// </summary>
protected override void OnNavigatedFrom(NavigationEventArgs args)
{
// 清空选中的列
CityList.SelectedIndex = -1;
CityList.SelectedItem = null;
}
}
}
第二个界面 异步调用Google的天气api,解析xml,然后绑定到客户端
天气预报类
ForecastPeriod.cs
using System.ComponentModel;
namespace WeatherForecast
{
/// <summary>
/// 天气预报绑定类
/// </summary>
public class ForecastPeriod : INotifyPropertyChanged
{
private string day_of_week;//星期
private int low;//最低温度
private int high;//最高温度
private string icon;//图片地址
private string condition;//天气情况
public event PropertyChangedEventHandler PropertyChanged;
public ForecastPeriod()
{
}
public string Day_of_week
{
get
{
return day_of_week;
}
set
{
if (value != day_of_week)
{
this.day_of_week = value;
NotifyPropertyChanged("Day_of_week");
}
}
}
public int Low
{
get
{
return low;
}
set
{
if (value != low)
{
this.low = value;
NotifyPropertyChanged("Low");
}
}
}
public int High
{
get
{
return high;
}
set
{
if (value != high)
{
this.high = value;
NotifyPropertyChanged("High");
}
}
}
public string Icon
{
get
{
return icon;
}
set
{
if (value != icon)
{
this.icon = value;
NotifyPropertyChanged("Icon");
}
}
}
public string Condition
{
get
{
return condition;
}
set
{
if (value != condition)
{
this.condition = value;
NotifyPropertyChanged("Condition");
}
}
}
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
天气预报列表类 以及异步调用解析的方法
Forecast.cs
using System;
using System.Net;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace WeatherForecast
{
/// <summary>
/// 天气类以及处理解析异步请求
/// </summary>
public class Forecast : INotifyPropertyChanged
{
// 天气预报的城市
private string city;
// 天气预报的时间
private string forecast_date;
public event PropertyChangedEventHandler PropertyChanged;
// 不同时间段的天气预报集合
public ObservableCollection<ForecastPeriod> ForecastList
{
get;
set;
}
public String City
{
get
{
return city;
}
set
{
if (value != city)
{
city = value;
NotifyPropertyChanged("City");
}
}
}
public String Forecast_date
{
get
{
return forecast_date;
}
set
{
if (value != forecast_date)
{
forecast_date = value;
NotifyPropertyChanged("Forecast_date");
}
}
}
public Forecast()
{
ForecastList = new ObservableCollection<ForecastPeriod>();
}
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
//////////////////////////////////////////////////////////////////////////////
/// <summary>
/// 获取Forecast类
/// </summary>
public void GetForecast(string cityPinyin)
{
UriBuilder fullUri = new UriBuilder("http://www.google.com/ig/api");
fullUri.Query = "weather=" + cityPinyin;
HttpWebRequest forecastRequest = (HttpWebRequest)WebRequest.Create(fullUri.Uri);
ForecastUpdateState forecastState = new ForecastUpdateState();
forecastState.AsyncRequest = forecastRequest;
forecastRequest.BeginGetResponse(new AsyncCallback(HandleForecastResponse),
forecastState);
}
/// <summary>
/// 异步获取信息
/// </summary>
/// <param name="asyncResult"></param>
private void HandleForecastResponse(IAsyncResult asyncResult)
{
ForecastUpdateState forecastState = (ForecastUpdateState)asyncResult.AsyncState;
HttpWebRequest forecastRequest = (HttpWebRequest)forecastState.AsyncRequest;
forecastState.AsyncResponse = (HttpWebResponse)forecastRequest.EndGetResponse(asyncResult);
Stream streamResult;
string city = "";
string forecast_date = "";
// 创建一个临时的ForecastPeriod集合
ObservableCollection<ForecastPeriod> newForecastList =
new ObservableCollection<ForecastPeriod>();
try
{
streamResult = forecastState.AsyncResponse.GetResponseStream();
//加载 XML
XElement xmlWeather = XElement.Load(streamResult);
// 解析XML
// http://www.google.com/ig/api?weather=Beijing
// 找到forecast_information节点获取city节点和forecast_date节点的信息
XElement xmlCurrent = xmlWeather.Descendants("forecast_information").First();
city = (string)(xmlCurrent.Element("city").Attribute("data"));
forecast_date = (string)(xmlCurrent.Element("forecast_date").Attribute("data"));
ForecastPeriod newPeriod;
foreach (XElement curElement in xmlWeather.Descendants("forecast_conditions"))
{
try
{
newPeriod = new ForecastPeriod();
newPeriod.Day_of_week = (string)(curElement.Element("day_of_week").Attribute("data"));
newPeriod.Low = (int)(curElement.Element("low").Attribute("data"));
newPeriod.High = (int)(curElement.Element("high").Attribute("data"));
newPeriod.Icon = "http://www.google.com" + (string)(curElement.Element("icon").Attribute("data"));
newPeriod.Condition = (string)(curElement.Element("condition").Attribute("data"));
newForecastList.Add(newPeriod);
}
catch (FormatException)
{
}
}
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
//赋值City Forecast_date
City = city;
Forecast_date = forecast_date;
ForecastList.Clear();
// 赋值ForecastList
foreach (ForecastPeriod forecastPeriod in newForecastList)
{
ForecastList.Add(forecastPeriod);
}
});
}
catch (FormatException)
{
return;
}
}
}
public class ForecastUpdateState
{
public HttpWebRequest AsyncRequest { get; set; }
public HttpWebResponse AsyncResponse { get; set; }
}
}
xml的格式如图
第二个页面的代码
ForecastPage.xaml
<phone:PhoneApplicationPage
x:Class="WeatherForecast.ForecastPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">
<TextBlock x:Name="ApplicationTitle" Text="天气预报" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="{Binding City}" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
<Grid x:Name="ContentGrid" Grid.Row="1" Margin="12,0,12,0">
<ListBox Height="618" HorizontalAlignment="Left" Margin="0,5,0,0" Name="ForecastList" VerticalAlignment="Top" Width="474" Grid.RowSpan="2" SelectionChanged="ForecastList_SelectionChanged" >
<ListBox.ItemTemplate><!--数据绑定模板-->
<DataTemplate>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="80"/>
<RowDefinition Height="80"/>
<RowDefinition />
<RowDefinition Height="*" MinHeight="80" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="90" />
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="180"/>
<ColumnDefinition Width="90"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Day_of_week}" Foreground="LightBlue" FontSize="40" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2"/>
<Image Source="{Binding Icon}" Grid.Column="0" Grid.Row="0" VerticalAlignment="Bottom" HorizontalAlignment="Right" Grid.ColumnSpan="2" />
<TextBlock Text="最低温度(K)" FontSize="30" Foreground="LightBlue" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2"/>
<TextBlock Text="{Binding Low}" FontSize="30" Foreground="White" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
<TextBlock Text="最高温度(K)" FontSize="30" Foreground="LightBlue" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2"/>
<TextBlock Text="{Binding High}" FontSize="30" Foreground="White" Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="2" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
<TextBlock Text="{Binding Condition}" FontSize="25" Foreground="White" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="4" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;
namespace WeatherForecast
{
public partial class ForecastPage : PhoneApplicationPage
{
Forecast forecast;
public ForecastPage()
{
InitializeComponent();
}
/// <summary>
/// 当该页面被链接打开时,会调用该事件
/// </summary>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// 获取传过来的City值
string cityPinyin = this.NavigationContext.QueryString["City"];
forecast = new Forecast();
//获取天气类
forecast.GetForecast(cityPinyin);
// 设置页面数据绑定到forecast
DataContext = forecast;
// 设置ForecastList绑定到forecast.ForecastList
ForecastList.ItemsSource = forecast.ForecastList;
}
private void ForecastList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ForecastList.SelectedIndex = -1;
ForecastList.SelectedItem = null;
}
}
}
posted on 2011-03-05 18:18 linzheng 阅读(4317) 评论(36) 编辑 收藏 举报