window phone7.1 天气预报教程(四)ApplicationBar的设置与LongListSelector控件的使用

  到现在为止,我们只能显示一个城市的天气,可是如果想得到别的城市的天气呢,总不能去修改程序里的值啊.这样我们就需求添加一个选择城市的页面.

  首先,我们要在MainPage.xaml页面中添加一个设置按钮,这个按钮呢,你自己做一个按钮也行,要是WM7为什么预留了一个ApplicationBar的功能,我们可以直接使用它就行,在每个xaml的页面中.这个功能的代码,已经为什么写好了,只是被注释掉了.它就在前台代码的最下面.

  

看到了,我们只要把它进行解开就行了.这里简单说一句<shell:ApplicationBarIconButton>就是

   

看到了吧,而且对于<shell:ApplicationBar.MenuItems>则是点击省略号后,显示的二级菜单位了,你可以自己去试一下.

一般来说我们刚解锁的这个applicationbar的图片全是X这个X表示的是没有图片.我们可以去SDK中去找我们自己需求的图片,地址是:

C;/programe file/Microsoft SDKs/window phone/v7.1/Icon/dark下面去选择你要的图片,然后将图片复制到你的项目中,然后修改图片的属性,Build Action:Content

Copy to Output: Copy if newer就可以了


我们为appllicationbar添加事件,
 Click="ApplicationBarIconButton_Click"

 /// <summary>
        /// 设置按钮点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ApplicationBarIconButton_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/SetCity.xaml", UriKind.Relative));
        }

SetCity.xaml页面就是我们的选择城市的页面,这里我们用到一个控制是LongListSelector控件,它需求你安装Silverlight for Windows Phone Toolkit才可以使用.http://silverlight.codeplex.com/releases/view/55034这个是它的下载地址.这个控件的好处是,可以让我们所选择的城市像电话号码薄一样显示出来,我们先看一下效果


看到了,是不是很好看,而且选择起来,也相当方便

我们看一下前台代码:

<phone:PhoneApplicationPage xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"  
    x:Class="WeatherForecast.SetCity"
    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">
    
    <phone:PhoneApplicationPage.Resources>
        <DataTemplate x:Key="GroupHeader">
            <Border Background="{StaticResource PhoneAccentBrush}" Margin="{StaticResource PhoneTouchTargetOverhang}" Padding="{StaticResource PhoneTouchTargetOverhang}">
                <TextBlock Text="{Binding Key}"></TextBlock>
            </Border>
        </DataTemplate>
        <DataTemplate x:Key="GroupItem">
            <Border Background="{StaticResource PhoneAccentBrush}" Margin="{StaticResource PhoneTouchTargetOverhang}" Padding="{StaticResource PhoneTouchTargetOverhang}">
                <TextBlock Text="{Binding Key}" Style="{StaticResource PhoneTextLargeStyle}"></TextBlock>
            </Border>
        </DataTemplate>
        <DataTemplate x:Key="ListHeader">
            <TextBlock Text="选择城市" Style="{StaticResource PhoneTextTitle1Style}"></TextBlock>
        </DataTemplate>
        <DataTemplate x:Key="Itemtmp">
            <Grid>
                <TextBlock Text="{Binding city}"></TextBlock>
            </Grid>
        </DataTemplate>
    </phone:PhoneApplicationPage.Resources>

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="page name" 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">
            <toolkit:LongListSelector x:Name="llsCity" SelectionChanged="llsCity_SelectionChanged" Background="Transparent" 
        ItemTemplate="{StaticResource Itemtmp}" 
        ListHeaderTemplate="{StaticResource ListHeader}" 
        GroupHeaderTemplate="{StaticResource GroupHeader}" 
        GroupItemTemplate="{StaticResource GroupItem}">
    </toolkit:LongListSelector>
        </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>

LongListSelector控件,可以让你自己设计它的样式模板,包括信息,头部等.这里我们就采用了默认情况.

我们来看后台代码,还记得在1中我给的哪个xml文件吗,里面的所有城市的信息.在这里我们要用它来做数据源.

第一步,我们先建立一个类,表示,省,市,以及市的ID

/// <summary>
        /// 定义城市信息类
        /// </summary>
        public class CityInfo
        {
            public string city { get; set; }
            public string province { get; set; }
            public string cityid { get; set; }
        }

第二步,我们要重载接口IGrouping主要是用来把得到的信息,拼接起来

/// <summary>
        /// 定义城市信息类
        /// </summary>
        public class CityInfo
        {
            public string city { get; set; }
            public string province { get; set; }
            public string cityid { get; set; }
        }
/// <summary>
        /// 重载接口
        /// </summary>
        /// <typeparam name="TKey"><peparam>
        /// <typeparam name="TElement"><peparam>
        public class GroupingLayer<TKey, TElement> : IGrouping<TKey, TElement>
        {
            //分组数据
            private readonly IGrouping<TKey, TElement> grouping;
            //初始化
            public GroupingLayer(IGrouping<TKey, TElement> unit)
            {
                grouping = unit;
            }
            //唯一的键值
            public TKey Key
            {
                get { return grouping.Key; }
            }
            //重载判断相等方法
            public override bool Equals(object obj)
            {
                GroupingLayer<TKey, TElement> that = obj as GroupingLayer<TKey, TElement>;
                return (that != null) && (this.Key.Equals(that.Key));
            }
            public IEnumerator<TElement> GetEnumerator()
            {
                return grouping.GetEnumerator();
            }
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return grouping.GetEnumerator();
            }
        }

第三步,添加数据绑定代码

/// <summary>
        /// 从XML数据中取出省份,市信息
        /// </summary>
        public void GetInfo()
        {
            var xDoc = XDocument.Load("data/city.xml");

            List<CityInfo> listCity = new List<CityInfo>();

            var info = from city in xDoc.Descendants("Citys")
                       select new
                       {
                           province = city.Element("province").Value,
                           cityc = city.Element("city").Value,
                           cityid = city.Element("cityid").Value
                       };
            foreach (var c in info)
            {
                listCity.Add(new CityInfo() { province = c.province, city = c.cityc, cityid = c.cityid });       
            }

            var selected = from c in listCity
                           group c by c.province into n
                           select new GroupingLayer<string, CityInfo>(n);

            this.llsCity.ItemsSource = selected;
        }

好,我们在构造函数中调用第三步的方法,来看一下效果,是不是显示出来,哪么显示之后,就是我们要点击城市之后,跳动回显示天气的页面,把选择的城市天气显示出来

这里的程序,就和(三)里的一样了,调用webclient写取得你要选择城市的天气.代码如下:

/// <summary>
        /// 选择城市时对数据进行更新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void llsCity_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            CityInfo c = this.llsCity.SelectedItem as CityInfo;
            if (c!=null)
            {
                
                webclient(c.cityid);
               
            }
        }


        /// <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 + ".html", UriKind.Absolute));
        }

        /// <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();

                UpdateXML(json);
            }
            catch (Exception ex)
            {
                MessageBox.Show("连接中央气象局出错!");
                //ReadXml();
            }
        }

这里的UpdateXML方法,是用来更新我们的临时存储空间中的数据信息的,还记得上次我们说的吗.第一次加载的时候,会先加载的数据


/// <summary>
        /// 更新XML文件,取得最新的数据
        /// </summary>
        /// <param name="json"></param>
        public void UpdateXML(JObject json)
        {


            if (iso.FileExists("weatherData.xml"))
            {
                iso.DeleteFile("weatherData.xml");


                IsolatedStorageFileStream isfs = new IsolatedStorageFileStream("weatherData.xml", FileMode.Create, iso);

                XElement xe = new XElement("weatherInfo",
                    new XElement("city", (string)json["weatherinfo"]["city"]),
                    new XElement("cityid", (string)json["weatherinfo"]["cityid"]),
                    new XElement("date_y", (string)json["weatherinfo"]["date_y"]),
                    new XElement("week", (string)json["weatherinfo"]["week"]),
                    new XElement("temp1", (string)json["weatherinfo"]["temp1"]),
                    new XElement("temp2", (string)json["weatherinfo"]["temp2"]),
                    new XElement("temp3", (string)json["weatherinfo"]["temp3"]),
                    new XElement("temp4", (string)json["weatherinfo"]["temp4"]),
                    new XElement("temp5", (string)json["weatherinfo"]["temp5"]),
                    new XElement("temp6", (string)json["weatherinfo"]["temp6"]),
                    new XElement("weather1", (string)json["weatherinfo"]["weather1"]),
                    new XElement("weather2", (string)json["weatherinfo"]["weather2"]),
                    new XElement("weather3", (string)json["weatherinfo"]["weather3"]),
                    new XElement("weather4", (string)json["weatherinfo"]["weather4"]),
                    new XElement("weather5", (string)json["weatherinfo"]["weather5"]),
                    new XElement("weather6", (string)json["weatherinfo"]["weather6"]),
                    new XElement("wind1", (string)json["weatherinfo"]["wind1"]),
                    new XElement("wind2", (string)json["weatherinfo"]["wind2"]),
                    new XElement("wind3", (string)json["weatherinfo"]["wind3"]),
                    new XElement("wind4", (string)json["weatherinfo"]["wind4"]),
                    new XElement("wind5", (string)json["weatherinfo"]["wind5"]),
                    new XElement("wind6", (string)json["weatherinfo"]["wind6"]),
                    new XElement("info", (string)json["weatherinfo"]["index48_d"]));

                XDocument xdoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), new XComment("天气数据"), new XElement("root", xe));

                StreamWriter sw = new StreamWriter(isfs);
                xdoc.Save(sw);
                sw.Close();
                isfs.Close();

                NavigationService.Navigate(new Uri("/MainPage.xaml?cityid=" + (string)json["weatherinfo"]["cityid"], UriKind.Relative));
            }
        }

运行一下看一下效果如何,呵呵.....是不是很有帅呢.这里其实还有几个问题,

第一,正常情况你,天气情况不应该是时时刷新的,应该设置一下,每隔几小时刷新一次,

第二,现在只是保留了一个城市的信息,你可以修改一下,做到保留几个城市的信息.



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值