window phone7.1 天气预报教程(二)WebClient获取天气和json数据解析显示

来源:互联网 发布:php全栈 招聘 编辑:程序博客网 时间:2024/05/22 12:57

  上一节,我们已经把显示后四天天气的usercontrol做完了.今天我们来做一点更有意思的,就是把天气真实的显示出来,这里面要用到的知识点是webClient和json这二点.

  好了,开始,我们先把mainpage.xaml页面的样式简单修改一下.

  代码如下:(这里我用的是测试页面-Page1.xaml)大家不要直接全页复制

  

<phone:PhoneApplicationPage     x:Class="WeatherForecast.Page1"    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"    xmlns:my="clr-namespace:WeatherForecast"    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">    <!--LayoutRoot is the root grid where all page content is placed-->    <Grid x:Name="LayoutRoot" Background="Transparent" Loaded="LayoutRoot_Loaded">        <Grid.ColumnDefinitions>            <ColumnDefinition Width="240*" />            <ColumnDefinition Width="240*" />        </Grid.ColumnDefinitions>        <Grid.RowDefinitions>            <RowDefinition Height="Auto"/>            <RowDefinition Height="*"/>        </Grid.RowDefinitions>        <!--TitlePanel contains the name of the application and page title-->        <StackPanel x:Name="TitlePanel" Margin="12,17,0,28" Grid.ColumnSpan="2">            <TextBlock x:Name="PageTitle" Text="" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>        </StackPanel>        <!--ContentPanel - place additional content here-->        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"  Grid.ColumnSpan="2">            <Grid.ColumnDefinitions>                <ColumnDefinition Width="226*" />                <ColumnDefinition Width="230*" />            </Grid.ColumnDefinitions>            <Grid.RowDefinitions>                <RowDefinition Height="162*" />                <RowDefinition Height="104*" />                <RowDefinition Height="112*" />                <RowDefinition Height="116*" />                <RowDefinition Height="113*" />            </Grid.RowDefinitions>            <my:ForecastTemplate x:Name="day1" Grid.Column="1" Grid.Row="1" Height="100" Width="230" Weekday="" Temp="" imageUrl=""></my:ForecastTemplate>            <my:ForecastTemplate x:Name="day2" Grid.Column="1" Grid.Row="2" Height="100" Weekday="" Temp="" imageUrl="" ></my:ForecastTemplate>            <my:ForecastTemplate x:Name="day3" Grid.Column="1" Grid.Row="3" Height="101" Width="230" Weekday="" Temp="" imageUrl="" ></my:ForecastTemplate>            <my:ForecastTemplate x:Name="day4" Grid.Column="1" Grid.Row="4" Height="101" Width="230" Weekday="" Temp="" imageUrl="" ></my:ForecastTemplate>            <Image x:Name="todayImage" Height="150" Width="225"></Image>            <TextBlock x:Name="todaytemp" Text="" Grid.Column="0" Grid.Row="1" Width="225" Height="100" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="40"></TextBlock>            <TextBlock x:Name="todaywhe"  Grid.Column="1" Grid.Row="0" Width="230" Height="150" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="24" TextWrapping="Wrap" Text=""></TextBlock>            <TextBlock x:Name="todaydate" Text="" Grid.Column="0" Grid.Row="2" Width="225" Height="100" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="24" TextWrapping="Wrap"></TextBlock>            <TextBlock x:Name="wtInfo"  Grid.Column="0" Grid.Row="3" TextWrapping="Wrap" Grid.RowSpan="2" FontSize="24"></TextBlock>        </Grid>    </Grid>     <!--Sample code showing usage of ApplicationBar-->    <!--<phone:PhoneApplicationPage.ApplicationBar>        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>            <shell:ApplicationBar.MenuItems>                <shell:ApplicationBarMenuItem Text="MenuItem 1"/>                <shell:ApplicationBarMenuItem Text="MenuItem 2"/>            </shell:ApplicationBar.MenuItems>        </shell:ApplicationBar>    </phone:PhoneApplicationPage.ApplicationBar>--></phone:PhoneApplicationPage>

页面设计比较简单的, 没有什么好多说的,这里只有一点就是我在

<Grid x:Name="LayoutRoot" Background="Transparent" Loaded="LayoutRoot_Loaded">
加了一个loaded事件,就是在页面加载的时候,要实现的事件.

下面我们来看一下后台的代码

这里面,要先说一下前面提到的二个知识点:

1,webClient:提供向 URI 标识的资源发送数据和从 URI 标识的资源接收数据的公共方法。

  这里呢,我们用到的就是从URI标识的资源接收数据.

2,json:什么时候用到呢,就是把从webClient取来的数据进行解析,因为得到的数据是json形式的,

  我们要用到一个json的dll文件,大家可以到 http://json.codeplex.com/ 去下,然后加载进项目

  这里的天气情况我是从中央气象台的API中提取的,它返回的值就是json值,我们看一下

  

{"weatherinfo":{"city":"哈尔滨","city_en":"haerbin","date_y":"2012年7月6日","date":"","week":"星期五","fchh":"11","cityid":"101050101","temp1":"31℃~20℃","temp2":"32℃~22℃","temp3":"33℃~23℃","temp4":"33℃~22℃","temp5":"31℃~22℃","temp6":"30℃~21℃","tempF1":"87.8℉~68℉","tempF2":"89.6℉~71.6℉","tempF3":"91.4℉~73.4℉","tempF4":"91.4℉~71.6℉","tempF5":"87.8℉~71.6℉","tempF6":"86℉~69.8℉","weather1":"晴","weather2":"晴","weather3":"多云","weather4":"晴转多云","weather5":"多云","weather6":"多云转晴","img1":"0","img2":"99","img3":"0","img4":"99","img5":"1","img6":"99","img7":"0","img8":"1","img9":"1","img10":"99","img11":"1","img12":"0","img_single":"0","img_title1":"晴","img_title2":"晴","img_title3":"晴","img_title4":"晴","img_title5":"多云","img_title6":"多云","img_title7":"晴","img_title8":"多云","img_title9":"多云","img_title10":"多云","img_title11":"多云","img_title12":"晴","img_title_single":"晴","wind1":"南风3-4级转小于3级","wind2":"南风3-4级转西南风小于3级","wind3":"西南风3-4级转小于3级","wind4":"南风3-4级转小于3级","wind5":"东南风3-4级转小于3级","wind6":"东南风3-4级转小于3级","fx1":"南风","fx2":"南风","fl1":"3-4级转小于3级","fl2":"3-4级转小于3级","fl3":"3-4级转小于3级","fl4":"3-4级转小于3级","fl5":"3-4级转小于3级","fl6":"3-4级转小于3级","index":"炎热","index_d":"天气炎热,建议着短衫、短裙、短裤、薄型T恤衫、敞领短袖棉衫等清凉夏季服装。","index48":"炎热","index48_d":"天气炎热,建议着短衫、短裙、短裤、薄型T恤衫、敞领短袖棉衫等清凉夏季服装。","index_uv":"很强","index48_uv":"很强","index_xc":"适宜","index_tr":"适宜","index_co":"较不舒适","st1":"29","st2":"21","st3":"30","st4":"23","st5":"32","st6":"23","index_cl":"较适宜","index_ls":"极适宜","index_ag":"不易发"}}

这里简单做一下解释

city:城市名

city_en:城市的英文名

date_y:日期

week:星期

cityid:城市的代码

temp1:当天的温度 temp2不是第二天的,以此类推

weather1:当天天气

wind1:当天风向

index48_d:着装提示.

为了能够显示这些数据,我们需求加一个类文件用来存取这些数据,以便读取和赋值

WeatherInfo.cs

using System;using System.Net;using System.Windows;using System.Windows.Controls;using System.Windows.Documents;using System.Windows.Ink;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Animation;using System.Windows.Shapes;namespace WeatherForecast{    public class WeatherInfo    {        public string city { get; set; }        public string cityid { get; set; }        public string date_y { get; set; }        public string week { get; set; }        public string temp1 { get; set; }        public string temp2 { get; set; }        public string temp3 { get; set; }        public string temp4 { get; set; }        public string temp5 { get; set; }        public string temp6 { get; set; }        public string weather1 { get; set; }        public string weather2 { get; set; }        public string weather3 { get; set; }        public string weather4 { get; set; }        public string weather5 { get; set; }        public string weather6 { get; set; }        public string wind1 { get; set; }        public string wind2 { get; set; }        public string wind3 { get; set; }        public string wind4 { get; set; }        public string wind5 { get; set; }        public string wind6 { get; set; }        public string info { get; set; }    }}

好准备工作完事了.我们开始我们的后台编码:

第一步,我们要先进行加载中央气象局的数据,我写了一个方法:

/// <summary>        /// 加载远程中央气象局数据        /// </summary>        public void webclient(string cityid)        {            WebClient wc = new WebClient();            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);            wc.DownloadStringAsync(new Uri("http://m.weather.com.cn/data/" + cityid, UriKind.Absolute));        }

这里说一下,这里的webClient 取数据是异步进行的.我相信大家看到这个wc.DownloadStringArync也就明了.

第二步:这里我们还要实现wc.DownloadStringCompleted这个方法,wc.DownloadStringCompleted这个方法是在异步获取完数据之后执行的.在这个方法里,我们就要把获取的天气数据读出来

/// <summary>        /// 异步加载完成后,向气象类写数据        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        public void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)        {            try            {                if (e.Result.Length < 1 || e.Error != null || e.Cancelled)                {                    MessageBox.Show("天气预报数据加载失败!原因:" + e.Error.Message);                    return;                }                JObject json = JObject.Parse(e.Result);                wi = new WeatherInfo                {                    city = (string)json["weatherinfo"]["city"],                    cityid = (string)json["weatherinfo"]["cityid"],                    date_y = (string)json["weatherinfo"]["date_y"],                    week = (string)json["weatherinfo"]["week"],                    info = (string)json["weatherinfo"]["index48_d"],                    wind1 = (string)json["weatherinfo"]["wind1"],                    temp1 = (string)json["weatherinfo"]["temp1"],                    temp2 = (string)json["weatherinfo"]["temp2"],                    temp3 = (string)json["weatherinfo"]["temp3"],                    temp4 = (string)json["weatherinfo"]["temp4"],                    temp5 = (string)json["weatherinfo"]["temp5"],                    weather1 = (string)json["weatherinfo"]["weather1"],                    weather2 = (string)json["weatherinfo"]["weather2"],                    weather3 = (string)json["weatherinfo"]["weather3"],                    weather4 = (string)json["weatherinfo"]["weather4"],                    weather5 = (string)json["weatherinfo"]["weather5"]                };                                Update();            }            catch (Exception ex)            {                MessageBox.Show("连接中央气象局出错!");                            }        }

这里面有一个方法Update()大家一眼就能看出是做什么的,对,它是把得到的数据赋值给前台的控制了.

可是这里有几个问题,我们还是得优先考虑一下,就是图片的显示,这个就需求单独的方法来处理.所以...

第三步:图片显示方法 (说实话,天气变化的情况太多了,本人也没有整明白到底有多少,上网查了一下,也没有查全,所以就根据平时自己能遇到的常天气进行了处理)

/// <summary>        /// 根据天气情况加载图片        /// </summary>        /// <param name="weather"></param>        /// <returns></returns>        public string Getpic(string weather)        {            string uri = "Images/";            if (weather == "晴")            {                uri += "sunday.png";            }            else if (weather == "阴")            {                uri += "overcast.png";            }            else if (weather == "雷阵雨")            {                uri += "ThunderShower.png";            }            else if (weather.Contains("云"))            {                uri += "cloudy.png";            }            else if (weather == "雨")            {                uri += "Rain.png";            }            else if (weather.Contains("雨") && weather != "雨" && weather != "雷阵雨")            {                uri += "Rain.png";            }            else            {                uri += "sunday.png";            }            return uri;        }

第四步:给前台控件赋值

/// <summary>        /// 将加载之后的数据绑定到前台控件中        /// </summary>        public void Update()        {            day1.Temp = wi.temp2;            day2.Temp = wi.temp3;            day3.Temp = wi.temp4;            day4.Temp = wi.temp5;            todaytemp.Text = wi.temp1;            todaywhe.Text = wi.weather1 + Environment.NewLine + wi.wind1;            todaydate.Text = wi.date_y + Environment.NewLine + wi.week;            wtInfo.Text = wi.info;            this.PageTitle.Text = wi.city;            int i;            for (i = 0; i < 7; i++)            {                if (weekMsg[i] == wi.week)                {                    break;                }            }            day1.Weekday = weekMsg[(i + 1) % 7];            day2.Weekday = weekMsg[(i + 2) % 7];            day3.Weekday = weekMsg[(i + 3) % 7];            day4.Weekday = weekMsg[(i + 4) % 7];            day1.imageUrl = Getpic(wi.weather2);            day2.imageUrl = Getpic(wi.weather3);            day3.imageUrl = Getpic(wi.weather4);            day4.imageUrl = Getpic(wi.weather5);                                   todayImage.Source = new BitmapImage(new Uri(Getpic(wi.weather1), UriKind.Relative));        }

写到这里,明眼人一看就知道,你的wi和weeMsg哪来的,哈哈....在前面定义一下吧,同时把第一步中的方法给load.

第四步:开始加载

 

WeatherInfo wi = null;        string[] weekMsg = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" };        public Page1()        {            InitializeComponent();        }        private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)        {            webclient("101050101.html");        }

现在运行一下看一下效果如何:


哈哈....还不错吧,可是有一点少的是什么呢,背景啊.墨迹天气会根据不同的天气换不同的背景啊.这个我们也可以做一手吗,现在做一个简单的修改

前台:为LayoutRoot这个Grid控件加一个初始化背景

<Grid x:Name="LayoutRoot">        <Grid.Background>            <ImageBrush ImageSource="Images/bgsun.png">            </ImageBrush>        </Grid.Background>        <Grid.ColumnDefinitions>            <ColumnDefinition Width="240*" />            <ColumnDefinition Width="240*" />        </Grid.ColumnDefinitions>        <Grid.RowDefinitions>            <RowDefinition Height="Auto"/>            <RowDefinition Height="*"/>        </Grid.RowDefinitions>

后台,加一个方法先:

 /// <summary>        /// 根据天气情况设备背景图片        /// </summary>        /// <param name="weather"></param>        /// <returns></returns>        public string GetBgpic(string weather)        {            string uri = "Images/";            if (weather == "晴")            {                uri += "bgsun.png";            }            else if (weather == "阴")            {                uri += "bgOvercast.png";            }            else if (weather == "雷阵雨")            {                uri += "bgThunderShower.png";            }            else if (weather.Contains("云"))            {                uri += "bgcloudy.png";            }            else if (weather.Contains("雪"))            {                uri += "bgSnow.png";            }            else if (weather.Contains("雨") && weather != "雨" && weather != "雷阵雨")            {                uri += "bgrain.png";            }            else            {                uri += "bgsun.png";            }            return uri;        }

在Upade()方法中加入:

ImageBrush ib = new ImageBrush();            ib.ImageSource = new BitmapImage(new Uri(GetBgpic(wi.weather1), UriKind.Relative));            this.LayoutRoot.Background = ib;

再预览一下,什么样了.

是不是爽多了.背景图片,你可以自己去找一些

http://download.csdn.net/detail/chenguang79/4414336

这是所有城市的天气代码.大家可以用一下,