[深入浅出Windows 10]应用实战:Bing在线壁纸

本章介绍一个使用Bing搜索引擎背景图接口实现的一个应用——Bing在线壁纸,讲解如何使用网络的接口来实现一个壁纸下载,壁纸列表展示和网络请求封装的内容。通过该例子我们可以学习到如何使用网络编程的知识和开放的接口来实现一些有趣的应用程序,如何在项目中封装相关的功能模块,从而进一步地了解Windows 10应用程序开发的过程。

23.1 应用实现的功能

微软的Bing搜索引擎每天都会挑选出一张图片作为今天的主题,并且会对图片的含义或者图片所代表的意思进行一番解说,每天的图片和故事都不一样,并且有时候不同国家挑选的图片和故事也不一样。你在网页上打开Bing搜索的中国区主页(http://cn.bing.com/)那么就可以看到今天的bing壁纸的内容和故事,每天都给用户带来有内涵有深度的图片和故事。在桌面的浏览器看到的Bing壁纸会很大,除此之外Bing也有手机的版本,对于手机版本Bing也是适配和符合手机分辨率的壁纸大小。

接下来我们要实现的Bing在线壁纸的应用程序是使用了微软的Bing壁纸获取的接口,把Bing搜索引擎每天的壁纸和故事通过网络接口来获取,然后在应用程序中显示出来。因为Bing壁纸每天都是不一样的,所以我们要实现的应用可以让用户不仅仅可以看到今天的壁纸和故事,也可以获取到以前的壁纸和故事。在Bing在线壁纸应用里面主要实现了两个功能,一个是显示出今天中国的壁纸主题,第二个是可以根据时间来获取壁纸的主题和故事,然后使用列表控件把主要国家的壁纸和故事展示出来,同时用户可以对壁纸进行相关的操作,如在浏览器打开,收藏等功能。

23.2 获取Bing壁纸的网络接口

Bing壁纸获取的网络接口网址格式如下所示:

http://appserver.m.bing.net/BackgroundImageService/TodayImageService.svc/GetTodayImage?dateOffset=0&urlEncodeHeaders=true&osName=windowsPhone&osVersion=8.10&orientation=480x800&deviceName=WP8&mkt=en-US

这个接口可以通过HTTP的Get请求来获取,可以直接在浏览器中打开链接变可以获取到图片的显示效果如图23.1所示。下面我们来看一下接口链接所传递过去的一些参数的说明。

(1)dateOffset表示已经过去的天数,比如0表示是今天,1则表示是昨天,4表示是获取4天前的壁纸,以此类推。

(2)orientation表示是获取的壁纸图片的分辨率,你可以设置为480×800、1024×768和800×480。

(3)mkt表示是国家地区的语言编码,你可以通过不同的语言编码来获取不同的国家地区的Bing壁纸图片和信息,比如可以设置为zh-CN、en-US等。

那么直接从使用该接口进行下载获取到的数据是整张图片的数据,如果要获取到图片的主题和故事,需要通过HTTP头相关的参数来获取。我们再利用一下IE浏览器,在IE浏览器上再次打开上面的链接,然后从浏览器的设置选项,找到“F12开发人员工具”的选项,点击启动IE浏览器的开发人员工具,然后在这里查看网络请求的头信息。找到网络类别,选择“详细信息”->“响应标头”就可以看到HTTP请求返回的响应头的信息,如图23.2所示。在这个响应头里面我们主要是要找到关于图片主题和故事的信息,如下所示:

(1)Image-Info-Credit(包含了图片的主题和版权信息)

Microphotograph%20of%20giant%20salvinia,%20a%20water%20fern%20(%C2%A9%20Martin%20Oeggerli/Visuals%20Unlimited,%20Inc.)

(2)Image-Info-Hotspot-1(图片的热点说明1

Let‘s%20switch%20the%20magnification%20back%20to...;images;Something%20more%20familiar;giant%20salvinia;;

(3)Image-Info-Hotspot-2(图片的热点说明2

Microscope%20slides%20may%20remind%20you%20of%20science%20class,%20but%20don‘t%20worry:%20There%20won‘t%20be%20a%20quiz.;images;Just%20marvel%20at%20how%20amazing%20plants%20can%20look%20up%20close;microphotography%20plants;;

23.3 壁纸请求服务的封装

在我们掌握了Bing壁纸的接口信息规则之后,接下来要做的事情就是根据业务的规则来封装壁纸请服务,把与壁纸请求关联的业务规则通过一个类来封装起来,然后提供相关的方法给外部来调用。通过对应用程序相关的服务封装成为公共的方法或者接口这是在程序架构上最基本的原则,这样的好处是不仅仅可以实现程序代码的共享,还可以实现解耦,程序逻辑清晰等好处。在我们要封装bing壁纸请求服务的时候,我们首先要考虑的问题是业务的情景,然后根据这个情景我们需要封装一个什么样的方法?传递进来的是什么参数?然后返回什么样的返回值?通过什么方式返回结果?首先根据我们的网络接口和业务情景,可以分析出来我们要实现的功能是,根据时间来获取当前的壁纸详情,壁纸详情会包括壁纸地址、壁纸主题、壁纸热点说明这些信息,然后同一天还需要获取多个国家的壁纸信息。通过这些分析,我们知道要传递进来的参数是时间,然后获取到的结果是多个国家在当天的壁纸信息。因为多个国家的壁纸信息,根据目前的接口情况是需要发起多次的请求才能获取到,并且HTTP的请求是异步请求,所在当发起这个网络服务请求时我们是很多必要去提供当前的进度信息,因此我们可以提供一个进度条的事件来返回进度结果、异常消息、结果信息等。通过上面的分析,现在基本清晰了这个壁纸请求服务的类该怎么封装了,下面我们来看一下封装的类和代码。

PictureInfo类:表示是壁纸信息的类,会包含了壁纸地址、主题、热点信息。
 ------------------------------------------------------------------------------------------------------------------
    /// <summary>
    /// 壁纸图片信息类
    /// </summary>
    public class PictureInfo
    {
        // 壁纸的热点说明信息
        public List<string> hotspot { get; set; }
        // 壁纸的主题
        public string imgTitle { get; set; }
        // 壁纸图片的地址
        public Uri imageUri { get; set; }
        // 壁纸位图对象
        public BitmapImage image { get; set; }
        // 国家代码
        public string countryCode { get; set; }
        // 壁纸图片信息类的初始化
        public PictureInfo(string _countryCode, string _imgTitle, string _imgUri)
        {
            countryCode = _countryCode;
            imgTitle = _imgTitle;
            imageUri = new Uri(_imgUri);
        }
    }
ProgressEventArgs类:表示获取壁纸信息的进度返回的参数类。
 ------------------------------------------------------------------------------------------------------------------
    // 下载进度参数类
    public class ProgressEventArgs : EventArgs
    {
        // 进度的百分比值
        public int ProgressValue { get; set; }
        // 是否完成了所有图片的下载
        public bool Complete { get; set; }
        // 是否发生异常
        public bool IsException { get; set; }
        // 异常消息
        public string ExceptionInfo { get; set; }
        // 下载的图片列表信息,未完成时为null
        public List<PictureInfo> Pictures { get; set; }
    }
WallpapersService类:表示获取壁纸信息的服务类,该类使用单例模式来设计,因为对于整个应用程序,这个服务类也只需要一个对象,更加适合设计成单例模式。
 ------------------------------------------------------------------------------------------------------------------
    /// <summary>
    /// 获取壁纸信息的服务类
    /// </summary>
    public class WallpapersService
    {
        // 距离今天的天数,表示获取壁纸的时间
        private int selectedDay;
        // 国家代码
        private List<string> countries = new List<string>(new string[] {
            "zh-CN", "fr-FR",  "de-DE","en-US",  "ja-JP","en-GB"});
        // 需要获取的请求次数
        private int http_times;
        // 总的请求次数
        private int http_times_all;
        // 是否已经开始下载了
        private bool downloading = false;
        // 已经下载的图片信息
        private Dictionary<int, List<PictureInfo>> allHaveDownloadPictures;
        // 完成进度事件
        public EventHandler<ProgressEventArgs> GetOneDayWallpapersProgressEvent;
        // 触发完成进度事件的方法
        private void OnGetOneDayWallpapersProgressEvent(ProgressEventArgs progressEventArgs)
        {
            if (GetOneDayWallpapersProgressEvent != null)
            {
                GetOneDayWallpapersProgressEvent.Invoke(this, progressEventArgs);
            }
        }
        private static WallpapersService _Current;
        // 单例对象
        public static WallpapersService Current
        {
            get
            {
                if (_Current == null)
                    _Current = new WallpapersService();
                return _Current;
            }
        }
        // 初始化对象
        private WallpapersService()
        {
            allHaveDownloadPictures = new Dictionary<int, List<PictureInfo>>();
        }
        /// <summary>
        /// 获取所选时间的图片
        /// </summary>
        /// <param name="selectedDay">表示距离今天的时间,0表示今天,1表示昨天……</param>
        public void GetOneDayWallpapers(int day)
        {
            // 如果当前正在下载图片则跳出该方法的调用
            if (downloading) return;
            // 把当前的服务标志位正在下载
            downloading = true;
            selectedDay = day;
            // 如果当前并没有该日期的数据则需要在字典对象里面添加上
            if(!allHaveDownloadPictures.Keys.Contains(selectedDay))
            {
                allHaveDownloadPictures.Add(selectedDay, new List<PictureInfo>());
            }
            // 拼接网络请求地址
            string format = "http://appserver.m.bing.net/BackgroundImageService/TodayImageService.svc/GetTodayImage?dateOffset=-{0}&urlEncodeHeaders=true&osName=windowsPhone&osVersion=8.10&orientation=480x800&deviceName=WP8Device&mkt={1}";
            http_times_all = http_times = countries.Count<string>();
            foreach (string country in countries)
            {
                // 判断该请求是否已经请求过,通过其所对应的日期和国家
                if (allHaveDownloadPictures[selectedDay].Select(item => item.countryCode == country).Count() == 0)
                {
                    //图片下载url
                    string bingUrlFmt = string.Format(format, selectedDay, country);
                    //开始下载
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(bingUrlFmt);
                    request.Method = "GET";
                    request.BeginGetResponse(result => this.responseHandler(result, request, country, bingUrlFmt), null);
                }
                else
                {
                    // 如果壁纸信息已经获取过则不要再重复获取,直接返回进度信息
                    SetProgress();
                }
            }
        }
        // 获取的壁纸图片信息回调方法
        private void responseHandler(IAsyncResult asyncResult, HttpWebRequest request, string myloc, string _imgUri)
        {
            HttpWebResponse response;
            try
            {
                response = (HttpWebResponse)request.EndGetResponse(asyncResult);
            }
            catch(Exception e)
            {
                downloading = false;
                // 返回异常信息
                OnGetOneDayWallpapersProgressEvent(
                    new ProgressEventArgs
                    {
                        IsException = true,
                        Complete = false,
                        ExceptionInfo = e.Message,
                        ProgressValue = 0,
                        Pictures = null
                    });
                return;
            }
            if (request.HaveResponse)
            {
                // 图片的热点说明信息
                List<string> _hotspot = new List<string>();
                string _imgTitle = "";
                // 通过HTTP请求头传输图片相关的信息
                foreach (string str in response.Headers.AllKeys)
                {
                    string str2 = str;
                    string str3 = response.Headers[str];
                    // 获取图片的说明信息和版权信息
                    if (str2.Contains("Image-Info-Credit"))
                    {
                        _imgTitle = WebUtility.UrlDecode(str3);
                    }
                    // 获取图片的热点介绍信息
                    else if (str2.Contains("Image-Info-Hotspot-"))
                    {
                        string[] strArray = WebUtility.UrlDecode(str3).Replace(" ","").Split(new char[] { ‘;‘ });
                        _hotspot.AddRange(strArray);
                    }
                }
                PictureInfo info = new PictureInfo(myloc, _imgTitle, _imgUri);
                info.hotspot = _hotspot;
                allHaveDownloadPictures[selectedDay].Add(info);
            }
            Debug.WriteLine("allHaveDownloadPictures[selectedDay].Count:" + allHaveDownloadPictures[selectedDay].Count);
            // 返回进度信息
            SetProgress();
        }
        // 返回进度的信息
        private void SetProgress()
        {
            http_times--;
            bool finish = http_times == 0;
            if (finish)
                downloading = false;
            // 返回结果
            OnGetOneDayWallpapersProgressEvent(
           new ProgressEventArgs {
               IsException = false,
               Complete = finish,
               ExceptionInfo = "",
               ProgressValue = (int)(((float)(http_times_all - http_times) / (float)http_times_all) * 100),
               Pictures = allHaveDownloadPictures[selectedDay]
           });
        }
    }

23.4 应用首页的设计和实现

那么在这一小节我们要实现的功能是Bing在线壁纸的首页页面,在首页页面主要是添加上最近几天的壁纸的链接,点击直接跳转到壁纸详情列表里面,因为一般情况大部分用户会比较关注最近的几天壁纸信息和主题,微软的这个壁纸通常都是会和最近的新闻或者节日相关。当然我们在首页也提供自定义的选择,让用户可以自定义选择几天前的壁纸信息的获取。首页的背景直接使用了当天中国地区的壁纸图片。

MainPage.xaml页面主要代码:应用首页的设计和逻辑。
 ------------------------------------------------------------------------------------------------------------------
    <Page.Resources>
        <!--定义了一个显示出用户自定义日期的面板的动画资源,动画的效果是从上往下拉出来-->
        <Storyboard x:Name="showMorePicture">
            <DoubleAnimation Storyboard.TargetName="topTransform" Storyboard.TargetProperty="Y" From="-300" To="0" Duration="0:0:0.3"></DoubleAnimation>
        </Storyboard>
    </Page.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid Opacity="0.5" Grid.RowSpan="2">
            <Grid.Background>
                <ImageBrush>
                    <ImageBrush.ImageSource>
                        <BitmapImage x:Name="background"></BitmapImage>
                    </ImageBrush.ImageSource>
                </ImageBrush>
            </Grid.Background>
        </Grid>
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,0,0,28">
            <TextBlock Text="Bing壁纸" FontSize="20"  />
        </StackPanel>
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <!--添加了5个HyperlinkButton控件,其中最后一个按钮会触发动画来显示出用户自定义日期的面板-->
            <StackPanel VerticalAlignment="Bottom">
                <HyperlinkButton Content="今天壁纸" x:Name="today" Click="today_Click"></HyperlinkButton>
                <HyperlinkButton Content="昨天壁纸" x:Name="yesterday" Click="yesterday_Click"></HyperlinkButton>
                <HyperlinkButton Content="2天前壁纸" x:Name="twodayago" Click="twodayago_Click"></HyperlinkButton>
                <HyperlinkButton Content="3天前壁纸" x:Name="threedayago" Click="threedayago_Click"></HyperlinkButton>
                <HyperlinkButton Content="更早的壁纸" x:Name="other" Click="other_Click"></HyperlinkButton>
            </StackPanel>
        </Grid>
    <!--自定义日期的面板-->
    <StackPanel x:Name="topStackPanel" Orientation="Vertical"  Grid.RowSpan="2" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Height="300" VerticalAlignment="Top">
        <!--面板默认是在屏幕最上方顶上,用户一开始并看不到-->
        <StackPanel.RenderTransform>
            <TranslateTransform x:Name="topTransform" Y="-300"></TranslateTransform>
        </StackPanel.RenderTransform>
        <TextBlock Text="选择时间:"  Margin="12 30 0 0" VerticalAlignment="Center"></TextBlock>
        <StackPanel Orientation="Horizontal" Margin="12 30 0 0">
            <!--使用两个AppBarButton来控制日期的增加和减少-->
            <AppBarButton Icon="Remove" IsCompact="True" x:Name="minus_bar" Click="minus_bar_Click" VerticalAlignment="Center"/>
            <TextBlock Text="4" x:Name="dayNumber" Margin="20 0 20 0" FontSize="20" VerticalAlignment="Center"></TextBlock>
            <AppBarButton Icon="Add" IsCompact="True" x:Name="plus_bar" Click="plus_bar_Click" VerticalAlignment="Center"/>
            <TextBlock Text="天前的壁纸"  VerticalAlignment="Center" Margin="24 0 0 0"></TextBlock>
        </StackPanel>
        <!--通过按钮事件来触发跳转到壁纸详情列表页面-->
        <Button Content="查看壁纸" x:Name="go" Click="go_Click"  Margin="20 30 0 0"></Button>
</StackPanel>
    </Grid>
MainPage.xaml.cs页面主要代码
 ------------------------------------------------------------------------------------------------------------------
    public sealed partial class MainPage : Page
    {
        private string TodayPictureUri = "http://appserver.m.bing.net/BackgroundImageService/TodayImageService.svc/GetTodayImage?dateOffset=-0&urlEncodeHeaders=true&osName=windowsphone&osVersion=8.10&orientation=480x800&deviceName=WP8Device&mkt=zh-CN";
        public MainPage()
        {
            this.InitializeComponent();
        }
        // 进入当前的页面
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            background.UriSource = new Uri(TodayPictureUri);
        }
        // 查看今天壁纸
        private void today_Click(object sender, RoutedEventArgs e)
        {
            Frame.Navigate(typeof(DayPicturesPage), 0);
        }
        // 查看昨天壁纸
        private void yesterday_Click(object sender, RoutedEventArgs e)
        {
            Frame.Navigate(typeof(DayPicturesPage), 1);
        }
        // 查看两天前壁纸
        private void twodayago_Click(object sender, RoutedEventArgs e)
        {
            Frame.Navigate(typeof(DayPicturesPage), 2);
        }
        // 查看三天前壁纸
        private void threedayago_Click(object sender, RoutedEventArgs e)
        {
            Frame.Navigate(typeof(DayPicturesPage), 3);
        }
        // 查看更早壁纸
        private void other_Click(object sender, RoutedEventArgs e)
        {
            showMorePicture.Begin();
        }
        // 查看更早壁纸,减少天数的图标按钮事件
        private void minus_bar_Click(object sender, RoutedEventArgs e)
        {
            int day = Int32.Parse(dayNumber.Text);
            if(day>0)
            {
                day--;
                dayNumber.Text = day.ToString();
            }
        }
        // 查看更早壁纸,增加天数的图标按钮事件
        private void plus_bar_Click(object sender, RoutedEventArgs e)
        {
            int day = Int32.Parse(dayNumber.Text);
            day++;
            dayNumber.Text = day.ToString();
        }
        // 前往查看自定义天数的壁纸
        private void go_Click(object sender, RoutedEventArgs e)
        {
            Frame.Navigate(typeof(DayPicturesPage), Int32.Parse(dayNumber.Text));
        }
    }

Bing在线壁纸的首页显示的效果如图23.3所示,点击“更早的壁纸”按钮会出现一个动画,自定义的面板会从上面下拉下来,显示的效果如图23.4所示。

23.5 手机和平板不同分辨率的适配

接下来我们要实现壁纸列表详情页面,在该列表里会展示某一天的壁纸信息,采用水平滚动的列表来显示壁纸的

在这里对两个地方做了特殊的适配,一个是“更早的壁纸”弹出层做了适配,还有一个地方是首页的背景图。下面先看下“更早的壁纸”弹出层的适配。

“更早的壁纸”弹出层的适配采用了适配触发器的方式去实现,当应用程序的宽度大于600像素的时候,弹出层的StackPanel面板采用水平排列的方式,并且高度从300像素改为150像素,如果手机横屏放置那么该适配效果也一样会生效。添加的适配代码如下所示:

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="SideBySideState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="600" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="topStackPanel.Orientation" Value="Horizontal"/>
                    <Setter Target="topStackPanel.Height" Value="150"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

当宽度大于500像素的时候,弹出层的显示效果如图23.5所示:

对首页背景图片的适配采用了后台C#代码来实现,当应用程序的宽度大于500像素的时候采用大分辨率的Bing图片,实现的思路是通过Window.Current.SizeChanged事件来获取应用程序的窗体变化情况,然后再进行判断是否选择大分辨率的图片。代码如下所示:

    public MainPage()
    {
        this.InitializeComponent();
        Window.Current.SizeChanged += Current_SizeChanged;
    }

    private void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
    {
        if (e.Size.Width <= 500)
        {
            background.UriSource = new Uri(TodayPictureUri);
        }
        else
        {
            background.UriSource = new Uri(TodayPictureUri_Big);
        }
    }

23.6 壁纸列表详情和操作的实现

接下来我们要实现壁纸列表详情页面,在该列表里会展示某一天的壁纸信息,采用水平滚动的列表来显示壁纸的图片显示和壁纸的热点信息说明,同时还提供了在浏览器打开和保存到应用文件的两个按钮操作功能。在该页面就需要去调用获取壁纸信息的服务类WallpapersService类的GetOneDayWallpapers方法来获取壁纸列表的信息,同时通过GetOneDayWallpapersProgressEvent事件把请求的进度在页面上显示出来,获取完成之后再把壁纸的信息绑定到列表控件。

DayPicturesPage.xaml文件主要代码:使用列表显示壁纸图片和信息的详情。
------------------------------------------------------------------------------------------------------------------
    <Page.Resources>
        <!--绑定转换器:把国家代码转化国家的名称-->
        <local:CountryNameConverter x:Key="CountryNameConverter" />
    </Page.Resources>
   ……
    <!--使用ItemsControl列表控件来显示壁纸的信息-->
    <ItemsControl  Grid.Row="1"  x:Name="pictureList"  >
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <!--设置列表控件的项目水平排列-->
                <StackPanel Orientation="Horizontal"></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.Template>
            <ControlTemplate>
                <!--设置列表控件的面板为水平垂直可滚动-->
                <ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility = "Visible">
                    <ItemsPresenter />
                </ScrollViewer>
            </ControlTemplate>
        </ItemsControl.Template>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <!--列表控件模板绑定壁纸的显示和相关的信息-->
                <Grid Width="340">
                    <Image Opacity="0.5"  Stretch="Uniform" >
                        <Image.Source>
                            <BitmapImage UriSource="{Binding imageUri}" ></BitmapImage>
                        </Image.Source>
                    </Image>
                    <!--绑定国家代码-->
                    <TextBlock FontSize="20" Text="{Binding countryCode,Converter={StaticResource CountryNameConverter}}" Margin="24 30 0 0"></TextBlock>
                    <StackPanel Margin="24 90 0 0" >
                        <!--绑定壁纸主题-->
                        <TextBlock FontSize="20" Text="{Binding imgTitle}"  TextWrapping="Wrap"></TextBlock>
                        <!--使用ListView列表绑定热点说明信息-->
                        <ListView ItemsSource="{Binding hotspot}" Height="300">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding}" FontSize="15" TextWrapping="Wrap"></TextBlock>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </StackPanel>
                    <!--保存和查看按钮-->
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" >
                        <AppBarButton Icon="View" Label="查看" x:Name="view" Click="view_Click"/>
                        <AppBarButton Icon="Save" Label="保存" x:Name="save" Click="save_Click"/>
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    <!--进度信息面板,在网络请求的过程显示,请问完成之后隐藏-->
    <StackPanel VerticalAlignment="Center" x:Name="tips">
        <!--进度条-->
        <ProgressBar  x:Name="progress" ></ProgressBar>
        <!--进度信息显示-->
        <TextBlock Text="" x:Name="info" HorizontalAlignment="Center" FontSize="30" TextWrapping="Wrap"></TextBlock>
    </StackPanel>
DayPicturesPage.xaml.cs文件主要代码
------------------------------------------------------------------------------------------------------------------
    public sealed partial class DayPicturesPage : Page
    {
        public DayPicturesPage()
        {
            this.InitializeComponent();
        }
        // 进入页面即开始加载网络的壁纸图片和信息
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (e.Parameter != null && e.Parameter is int)
            {
                // 订阅进度事件的处理程序
                WallpapersService.Current.GetOneDayWallpapersProgressEvent += OnOneDayWallpapersProgressEvent;
                // 调用壁纸请求服务类来获取壁纸信息
                WallpapersService.Current.GetOneDayWallpapers((int)e.Parameter);
            }
        }
        // 离开当前的页面则移除订阅的进度事件
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            WallpapersService.Current.GetOneDayWallpapersProgressEvent -= OnOneDayWallpapersProgressEvent;
            base.OnNavigatedFrom(e);
        }
        // 进度事件的处理程序
        private async void OnOneDayWallpapersProgressEvent(object sender, ProgressEventArgs e)
        {
           await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                {
                    if(e.IsException)
                    {
                        // 如果发生异常则显示异常信息
                        info.Text = "获取图片异常:"+e.ExceptionInfo;
                    }
                    else
                    {
                        // 正常返回设置进度条的值
                        progress.Value = e.ProgressValue;
                        // 进度完整
                        if(e.Complete)
                        {
                            // 把显示进度的面板隐藏
                            tips.Visibility = Visibility.Collapsed;
                            // 把壁纸信息绑定到列表中
                            pictureList.ItemsSource = e.Pictures;
                            Debug.WriteLine("e.Pictures.Count:" + e.Pictures.Count);
                        }
                    }
                });
        }
        // 查看按钮的事件处理程序
        private async void view_Click(object sender, RoutedEventArgs e)
        {
            PictureInfo pictureInfo = (sender as AppBarButton).DataContext as PictureInfo;
            // 在浏览器打开壁纸
            await Launcher.LaunchUriAsync(pictureInfo.imageUri);
        }
        // 保存按钮的事件处理程序
        private async void save_Click(object sender, RoutedEventArgs e)
        {
            PictureInfo pictureInfo = (sender as AppBarButton).DataContext as PictureInfo;
            List<Byte> allBytes = new List<byte>();
            // 把壁纸的图片文件保存到当前的应用文件里面
            using (var response = await HttpWebRequest.Create(pictureInfo.imageUri).GetResponseAsync())
            {
                using (Stream responseStream = response.GetResponseStream())
                {
                    byte[] buffer = new byte[4000];
                    int bytesRead = 0;
                    while ((bytesRead = await responseStream.ReadAsync(buffer, 0, 4000)) > 0)
                    {
                        allBytes.AddRange(buffer.Take(bytesRead));
                    }
                }
            }
           var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
                       "bingPicture"+DateTime.Now.Ticks+".jpg", CreationCollisionOption.ReplaceExisting);
           await FileIO.WriteBytesAsync(file, allBytes.ToArray());
        }
    }

本文来源于《深入浅出Windows 10通用应用开发》

源代码下载:http://vdisk.weibo.com/u/2186322691

目录:http://www.cnblogs.com/linzheng/p/5021428.html

欢迎关注我的微博@WP林政   微信公众号:wp开发(号:wpkaifa)

Windows10/WP技术交流群:284783431

时间: 2024-10-05 08:32:31

[深入浅出Windows 10]应用实战:Bing在线壁纸的相关文章

[深入浅出Windows 10]布局原理

5.2 布局原理 很多时候在编写程序界面的时候都会忽略了应用布局的重要性,仅仅只是把布局看作是对UI元素的排列,只要能实现布局的效果就可以了,但是在实际的产品开发中这是远远不够的,你可能面临要实现的布局效果要比常规布局更加复杂,这就需要对布局的技术知识有深入的理解和掌握才能够实现.要实现一个布局的效果,可能会有很多总布局方案,我们该怎么去选择实现的方法?如果要实现的一个布局效果是比较复杂的,我们该怎么去对这种布局规律进行封装?要解决这些问题,首要的问题就是需要我们对程序的布局原理有着深入的理解.

[深入浅出Windows 10]模拟实现微信的彩蛋动画

9.7 模拟实现微信的彩蛋动画 大家在玩微信的时候有没有发现节日的时候发一些节日问候语句如“情人节快乐”,这时候会出现很多爱心形状从屏幕上面飘落下来,我们这小节就是要模拟实现这样的一种动画效果.可能微信里面实现的动画效果都是采用固定的小图片来最为动画的对象,但是我们这小节要对该动画效果增加一些改进,也就是要实现的彩蛋动画的针对的图形形状是动态随机生成的,所以看到从屏幕上面飘落的图形都是形状不太一样的.下面来看一下如何实现星星飘落动画. 9.7.1 实现的思路 首先,我们来分析一下星星飘落动画的实

[深入浅出Windows 10]实现饼图控件

13.2 实现饼图控件 上一小节讲解了动态生成折线图和区域图,对于简单的图形这样通过C#代码来生成的方式是很方便的,但是当我们的图表要实现更加复杂的逻辑的时候,这种动态生成的方式就显得力不从心了,那就需要利用控件封装的方式来实现更加强大的图表控件功能.这一小节将来讲解怎样去用封装控件的方式去实现图表,用一个饼图控件作为例子进行分析讲解. 13.2.1 自定义饼图片形形状 饼图其实就是把一个圆形分成若干块,每一块代表着一个类别的数据,可以把这每一块的图形看作是饼图片形形状.要实现一个饼图控件,首先

[深入浅出Windows 10]分屏控件(SplitView)

4.18 分屏控件(SplitView) 分屏控件(SplitView)是Windows 10新增的控件类型,也是Windows 10通用应用程序主推的交互控件,通常和一个汉堡按钮搭配作为一种抽屉式菜单来进行呈现.控件的XAML语法如下: <SplitView> <SplitView.Pane > ……菜单面板的内容 </SplitView.Pane > ……主体内容 </SplitView> SplitView控件主要由两部分组成,一部分是菜单的面板,另一

[深入浅出WIndows 10]网络编程之HttpClient类

14.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类提供了一个简单的接口来处理最常见的任务,并为身份验证提供了适用于大多数方案的合理的默认设置.对于较为复杂的 HTTP 操作,更多的功能包括:执行常见操作(DELETE.GET.PUT 和 POST)的方法:获取.设置和删除 Cookie 的功能:支持常见的身份验证设置和模式:异步方法上提供的 HTTP

Windows 10 新特性 -- Bing Maps 3D地图开发入门(一)

本文主要内容是讲述如何创建基于 Windows Universal App 的Windows 10 3D地图应用,涉及的Windows 10新特性包括 Bing Maps 控件.Compiled data bindings (x:Bind),SplitView 和Hamburger. 本文中的示例源代码已在github 上共享( https://github.com/gaoxuesong/navigado ). 获取Bing Maps密钥 在 Universal Windows App 中使用必

《深入浅出Windows Phone 8.1 应用开发》基于Runtime框架全新升级版

<深入浅出Windows Phone 8.1 应用开发>使用WP8.1 Runtime框架最新的API重写了上一本<深入浅出Windows Phone 8应用开发>大部分的的内容,修改了上一本众多网友读者反馈的问题. 全书实例和项目演练的源代码免费下载: http://vdisk.weibo.com/s/zt_pyrfNHb99O 试读章节会在博客园持续更新: [深入浅出WP8.1(Runtime)]Windows Phone 8.1和Silverlight 8.1的区别 [深入浅

Windows 10 UAP(通用程序) 开发初体验(1) 之 开发准备

一.准备: 1.准备一个 10074或更高版本的Win10.可以通过 https://insider.windows.com/ 地址,加入Windows 的会员俱乐部免费获取的. 2.下载Visual Studio 2015 RC版. 可以在 https://www.visualstudio.com/ 这个地址下载到. 3.下载 Windows 10 development tools for Visual Studio 2015 RC. 地址:https://dev.windows.com/z

Windows 10 LTSB 2016 build 14393.3595

Windows 10 企业版 2016 长期服务版于2016年8月初正式推出,发行代号为周年更新“Anniversary Update”,系统版本为Version 1607,OS 内部版为14393.Windows 10 Enterprise LTSB相对Win10企业版来说,不会获得功能更新和改善,只有安全更新,提供了升级控制选项.LTSB版本可以说是官方Win10精简版.如果你需要全新安装,或者想收藏分享,本页整理收集了微软官方原版的下载连接和永久激活工具. 新版变化 Windows 10