×
Namespaces

Variants
Actions

Finnkino剧院的电影

From Nokia Developer Wiki
Jump to: navigation, search
WP Metro Icon File.png
WP Metro Icon Web.png
SignpostIcon XAML 40.png
SignpostIcon WP7 70px.png
Article Metadata

代码示例
兼容于
文章
翻译:
最后由 hamishwillee 在 19 Jul 2013 编辑

这篇文章解释了如何装载大量的基于XML的数据 - Finnkino剧院的电影 - 并在Windows Phone上显示剧院的时间表和电影数据。

Contents

简介

这篇文章展示如何创建Windows Phone应用程序来从Finnkino's XML中加载电影信息。剧院和电影的数据将被解析并显示在Windows Phone应用程序的不同的页面中。 应用程序设计为运行在WP7Panorama类型。首先应用程序连接到Finnkino's XML服务并加载当前显示的所有事件(一个XML文件)。之后,加载所有的剧院事件的信息和日程安排(仅限芬兰地区)。在Panorama视图的芬兰剧院都显示在一个ListBox控件(图片1)。这个程序的第二页中显示此应用程序的信息(这个应用程序是针对芬兰并只显示芬兰文)。

Theatre's in ListBox Legal information of the application

当用户选择主列表中的剧院时,今天的事件将显示(图3)。用户可以向上和向下滚动来了解这电影是否在今天选定的剧院中上演。所选影片的详细信息将显示在一个新的信息页面(图4)。显示的数据与Finnkino的XML数据相结合,它包含:戏剧和电影的名称,开始时间,长度,流派,年份,和大纲文本。

Movies in ListBox Movies Detail Page

用户可以点击“OSTA Liput” Button为选择的影片买门票。它为这个特定的影片页面打开Windows Phone默认浏览器,并开启Finnkino网站(图5)。如果XML数据包含预览信息,用户可以观看电影预告片:点击 "Katso Video" 按钮打开Windows Phone的默认电影应用程序加载并全屏显示电影预告片。

Finnikino Web Page Movie Trailer in FullScreen

这应用程序现在可以在Windows Marketplace上下载:Finnkino Elokuvat这篇文章也包括一些在Microsoft Visual Studio上测试应用程序的信息。

注意!Finnkino不是这个程序的创始人,因此对它的方案及其活动不负任何责任。

视频演示 - 如何操作

The media player is loading...

Finnkino的 XML 数据

Finnkino为现有的剧院和芬兰影片事件提供了很好的XML数据集(更详细的信息在这里Finnkino - XML)。 这个例子中将使用下面的XML源:

就像你所看到一样,这些XML feed有许多不同的数据并且我们要加载所有的! 注意!Finnkino可能随时更改XML数据的结构,所以你的这个实例可能也需要进行修改。

Windows Phone 7.1 SDK

为了在Windows Phone 7设备上开发应用程序,你需要安装的Windows Phone7.1 SDK。你可以在[1]为Windows Phone下载最新的SDK。

Windows Phone应用程序

要开始创建一个新的Windows Phone应用程序,首先启动Microsoft Visual Studio创建一个新项目,并选择Windows Phone应用程序模板。Panorama模板也可以,但我们选择Windows Phone应用程序模板。这样,我们可以并尽可能的保持我们的应用程序干净简介,然后我们可以利用代码来创造Panorama。

PTM FinnkinoProject.png

这个实例使用C#来编写后台代码。

在Windows Phone 7中解析XML

有许多不同的方法在Windows Phone 7上加载并解析XML数据。这个例子使用XML反序列化加载XML文档并将数据传递到一个deserializer。你需要为你的项目添加System.Xml.SerializationSystem.Xml.Linq两个引用。右击你的Solutions Explorer并选择"Add new Reference..."

将网络上的图片加载并显示

当你尝试从网上同时将大量的将图片加载到Windows Phone时,可能会有一个小问题。你可以从网上找到几个assembly来解决这个问题。这是一个很好的PhonePerformance assembly(你可以从[2]下载源代码并编译PhonePerformance assembly)。你必须先下载并解析它。将PhonePerformance.dll复制到你的电脑上并将它引用到你的项目中。 当你下载PhonePerformance.dll时可能会遇到警告(因为它是从网上下载的)。关闭你的Visual Studio。打开Windows Explorer并浏览你的PhonePerformance.dll文件。打开文件的属性来解除封锁。

启动画面图片

你可以找到你的项目文件夹中的默认SplashScreenImage.jpg图片。添加你自己定制的启动屏幕图片的最简单的方法就是在图篇编辑应用程序的工具中编辑这个图片。图片的大小为400x480并要设置它的"Build Action"为"Content",所以它将在XAP文件部署时被使用。

Splash Screen

上面的图片是作为一个在Finnkino Elokuvat应用程序的初始屏幕显示。

应用程序的后台代码中的类

在你的应用程序中创建一个新的类:

  1. 右击你项目中的Solutions Explorer
  2. 选择添加类

Events.cs

目前呈现的事件列表可从http://www.finnkino.fi/xml/Events/获得。这个例子只用EventID, SynopsisVideo url。EventIDSynopsis是用来作为一个Strings。Video url 是List<XElement>集合,因为可能有也可能没有这样一个视频网址。之后会在代码中进行解析(在屏幕上激活"Katso Video" 按钮)。

using System.Collections.Generic;
using System.Xml.Linq;
 
namespace FinnkinoElokuvat
{
public class Event
{
public string EventID { get; set; }
public string Synopsis { get; set; }
public List<XElement> Video { get; set; }
}
}

Show.cs

每个剧院电影被描述为一个XML数据Show节点(在这里:http://www.finnkino.fi/xml/Schedule/?area=1015 )。有很多资料可以利用,但这个例子中只用了在Show类中列出的信息。一些图像和以上视频的处理方式是相同的。

using System.Xml.Linq;
using System.Collections.Generic;
 
namespace FinnkinoElokuvat
{
public class Show
{
public string ID { get; set; }
public string EventID { get; set; }
public string Title { get; set; }
public string EventSmallImagePortrait { get; set; }
public string EventLargeImagePortrait { get; set; }
public string EventSmallImageLandscape { get; set; }
public List<XElement> Image { get; set; }
public string ShowStart { get; set; }
public string LengthInMinutes { get; set; }
public string Genres { get; set; }
public string ProductionYear { get; set; }
public string ShowURL { get; set; }
public string TheatreAndAuditorium { get; set; }
}
}

TheatreArea.cs

TheatreArea类是简洁的。它只是存储剧院的idname.。

namespace FinnkinoElokuvat
{
public class TheatreArea
{
public string id { get; set; }
public string name { get; set; }
}
}

Panorama

Design (MainPage.xaml)

Finnkino Elokuvat应用程序在Panorama中使用两页。第一页显示XML加载过程并显示在加载过程完成后所有在芬兰可用的剧院(地区)。第二个页面是用来显示一些应用(法律和信用)信息。 Phone Application页的Grid包含Panorama控件(controls:Panorama),其中包含Panorama标题,背景和两个Panorama Item。

<controls:Panorama Title="FiNNKiNO - Elokuvat">
<!-- controls:Panorama.TitleTemplate -->
<!-- controls:Panorama.Background -->
<!-- controls:PanoramaItem Header="teatterit" -->
<!-- controls:PanoramaItem Header="tietoja" -->
</controls:Panorama>

默认Panorama页面和标题的显示使用相当大的字体。你可以通过Panorama的TitleTemplate来改变字体。

<controls:Panorama.TitleTemplate>
<DataTemplate>
<TextBlock Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"
Foreground="White"
FontSize="60"
Margin="0,60,0,0"/>
</DataTemplate>
</controls:Panorama.TitleTemplate>

这里使用的字体大小为60(在此应用程序这似乎是不错的大小)且文本的前景色设置为白色,因为用黑色的渐变作为背景图片。

PTM FinnkinoPanoramaTitle.png

你可以为Panorama设置自己的背景图片。 在Images文件夹中创建你自己的项目(在Solution Explorer)并在Windows中将你的图片复制到该文件夹中。选择“添加现有项...浏览你的图片。这个示例中用一个1024x800大小的图片作为一个全景的背景。

<controls:Panorama.Background>
<ImageBrush ImageSource="Images/bg.png"/>
</controls:Panorama.Background>

最先被显示的是Panorama加载过程和在加载过程结束时显示剧院的名称(区)。

Panorama Page - Loading Panorama Page - Theatres

对于标题来说默认字体太大了(在这个示例中),修改方式与以上Panorama的标题相同, 使用PanoramaItem.HeaderTemplate元素。其实,Panorama中的第一项是一个grid,其中有TextBlock(显示加载过程)和ListBox,用来显示芬兰的剧院(地区)。加载完成后,TextBlock将被从Grid上删除。

<controls:PanoramaItem Header="teatterit">
<controls:PanoramaItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"
FontSize="50"
Foreground="White"
Margin="0,0,0,0"/>
</DataTemplate>
</controls:PanoramaItem.HeaderTemplate>
 
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock x:Name="InfoTextBlock" Foreground="White" />
<ListBox x:Name="TheatreListBox" FontSize="30" Foreground="White"/>
</Grid>
</controls:PanoramaItem>

Panorama的第二项显示应用程序的信息。在这个例子中,标题还是像先前那样修改。 PanoramaItem包含几个TextBlocksImages

Legal information

<controls:PanoramaItem Header="tietoja">
<controls:PanoramaItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"
FontSize="50" Foreground="White"
Margin="0,0,0,0"/>
</DataTemplate>
</controls:PanoramaItem.HeaderTemplate>
<Grid>
<TextBlock TextWrapping="Wrap"
Text="Finnkinon elokuvateattereiden päivän tarjonta Windows Mobilessa."
Foreground="White"
/>
<Image Source="Images/film.png"
Width="54"
Height="15"
VerticalAlignment="Top"
Margin="0,70"/>
<TextBlock Margin="0,100"
Foreground="White"
Text="Ohjelma lataa paljon tietoa verkosta... " TextWrapping="Wrap"/>
<Image Source="Images/film.png"
Width="54"
Height="15"
VerticalAlignment="Top"
Margin="0,240"/>
<TextBlock Margin="0,269,0,38"
TextWrapping="Wrap"
Foreground="White"
Text="Finnkino ei ole laatinut tätä ohjelmaa... " Height="297" />
</Grid>
</controls:PanoramaItem>

编程(MainPage.xaml.cs)

所有的XML加载过程都是在MainPage.xml.cs文件中发生的。本文原作者最初写这个例子时,在MainPage.xaml.cs文件中存储所有数据,但后来发现,数据存储在Appl.xaml.cs中更好,因为它比较容易实现页面之间的数据共享并很好的处理了墓碑情况。所以,请从App.xaml.cs中观看更多的有关theatreAreas, theatreEventstheatreShows的详细信息。本文原作者也在App.xaml.cs文件中定义dataLoaded变量,并在所有的数据加载后将它设置为true

此应用程序处理了大量的动态数据。在Windows Phone中应用程序可能被扔到后台(例如当一个新的电话进来或用户按下设备上的windows键运行不同的应用程序时)。如果你是幸运的,你的应用程序可以保持其在内存中的数据(你的应用程序是在休眠模式),当它再次在设备上运行时(运行在前台)你的应用程序可能正常工作。但Windows Phone也可能迫使你的应用程序进入墓碑模式,然后你必须存储应用程序数据并且在你的应用程序再次运行时加载它。稍后这篇文章会讨论更多这种内存处理。

MainPage类使用了以下变量。

int showsLoaded = 0;           // how many theatre's informations (shows) are loaded
App app = App.Current as App; // reference to application instance (there are all the List Collections for XML data)

splash screen结束后,或当用户从电影详细资料页回来时,OnNavigatedTo方法将被调用。在这里,我们第一次检查数据是否加载。如果我们启动应用程序,然而数据尚未加载,我们首先使用GetIsWorking()方法来检查是否网络已连接。

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// XML is not loaded yet, check if phone is connected to network
if (!app.dataLoaded) GetIsWorking();
// data is loaded, show theatres in listbox
else
{
// this method will be described later in this example
AddTheatres();
}
}

检查是否有可用的网络连接:

public void GetIsWorking()
{
// is there network connection available
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
MessageBox.Show("Ei verkkoyhteyttä");
InfoTextBlock.Text = "Elokuvateattereiden tietoja ei saada ladattua.\nSovellus vaatii verkkoyhteyden toimiakseen.\n\nTarkista matkapuhelimen verkkoyhteydet.";
return;
}
 
// network is available, start loading XML data
InfoTextBlock.Text = "Ladataan (odota)...\n-teatterien tiedot...";
GetTheatreAreas();
}

如果网络连接可用,我们开始加载剧院区的信息。在Windows Phone 7,你可以使用WebClient类异步加载数据。 当加载数据完成后或者有错误发生时TheatresDownloaded方法将被调用。

public void GetTheatreAreas()
{
WebClient downloader = new WebClient();
Uri uri = new Uri("http://www.finnkino.fi/xml/TheatreAreas/", UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(TheatresDownloaded);
downloader.DownloadStringAsync(uri);
}

TheatresDownloaded方法中,我们首先检查是否有错误发生,并在MessageBox中显示一些信息。如果没有错误,所有的戏院编号和名称的XML数据将被解析并加载。 TheatreArea对象将被创建,这些对象将被存储在列表List<TheatreArea> theatreAreas中(在App.xaml.cs文件)。

public void TheatresDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("Virhe Finnkinon XML-tietojen latauksessa!");
}
else
{
// parse XML data
XDocument document = XDocument.Parse(e.Result);
// create TheatreArea objects from loaded XML data
var data = from query in document.Descendants("TheatreArea")
select new TheatreArea
{
id = (string)query.Element("ID"),
name = (string)query.Element("Name")
};
// store all TheatreArea objects to List (in App.xaml.cs file)
app.theatreAreas = data.ToList<TheatreArea>();
// we don't use the first element at TheatreAreas data
app.theatreAreas.RemoveAt(0);
// start loading events
GetEvents();
}
}

所有Movie Events将被使用WebClient类加载

public void GetEvents()
{
InfoTextBlock.Text += "\n-elokuvien tiedot...";
WebClient downloader = new WebClient();
Uri uri = new Uri("http://www.finnkino.fi/xml/Events/", UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(EventsDownloaded);
downloader.DownloadStringAsync(uri);
}

当Events数据加载完成或者有错误发生时,EventsDownloaded方法将被调用。如果没有错误,ID's, SynopsisVideo Url的XML 数据将被加载并解析。首先,事件对象将被创建,并且这些对象将存储在列表List<Event> theatreEvents中(在App.xaml.cs文件)。

public void EventsDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("Virhe Finnkinon XML-tietojen latauksessa!");
}
else
{
// parse XML data
XDocument document = XDocument.Parse(e.Result);
// create Event objects from loaded XML data
var data = from query in document.Descendants("Event")
select new Event
{
EventID = (string)query.Element("ID"),
Synopsis = (string)query.Element("Synopsis"),
Video = query.Descendants("Videos").Descendants("EventVideo").ToList<XElement>()
};
// store all Event objects to List (in App.xaml.cs file)
app.theatreEvents = data.ToList<Event>();
// start loading schedules
GetSchedule();
}
}

所有的Theatre Schedules都将被使用WebClient类加载。在时用剧院时,这个类将被重复利用。

public void GetSchedule()
{
// get the theatre id
string area = app.theatreAreas[showsLoaded].id;
InfoTextBlock.Text += "\n-teatterin elokuvat - (" + area + ")...";
WebClient downloader = new WebClient();
// start loading this theatre schedule
Uri uri = new Uri("http://www.finnkino.fi/xml/Schedule/?area=" + area, UriKind.Absolute);
downloader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(ScheduleDownloaded);
downloader.DownloadStringAsync(uri);
}

Schedule数据加载完成或者有错误发生时,ScheduleDownloaded方法将被调用。如果没有错误,将Show对象将被创建,并且这些对象将存储在列表List<List<Show>> theatreShows集中(在App.xaml.cs文件)。

图像并不总是包含在XML数据中,这将导致一个小问题。我们不得不首先的查询图像的子节点(创建Show对象),然后检查是否有图像存在。这个例子添加不同大小的*. PNG图像到Show对象,如果图像节点在XML数据中是空的。你必须添加自己的图像到项目中。

void ScheduleDownloaded(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Result == null || e.Error != null)
{
MessageBox.Show("Virhe Finnkinon XML-tietojen latauksessa!");
}
else
{
// parse XML data
XDocument document = XDocument.Parse(e.Result);
// create Show objects from loaded XML data
var data = from query in document.Descendants("Show")
select new Show
{
ID = (string)query.Element("ID"),
EventID = (string)query.Element("EventID"),
Title = (string)query.Element("Title"),
ShowStart = (string)query.Element("dttmShowStart"),
LengthInMinutes = (string)query.Element("LengthInMinutes"),
Genres = (string)query.Element("Genres"),
ProductionYear = (string)query.Element("ProductionYear"),
ShowURL = (string)query.Element("ShowURL"),
TheatreAndAuditorium = (string)query.Element("TheatreAndAuditorium"),
Image = query.Descendants("Images").ToList<XElement>()
};
// create a new list (for this theatre shows)
List<Show> shows = new List<Show>();
shows = data.ToList<Show>();
 
// check if there are images in XML - shows - (add No*.png if not)
for (int i = 0; i < shows.Count; i++)
{
// is there EventSmallImagePortrait image
try
{
shows[i].EventSmallImagePortrait = (string) shows[i].Image.Descendants("EventSmallImagePortrait").ElementAt(0);
}
catch (ArgumentOutOfRangeException)
{
shows[i].EventSmallImagePortrait = "Images/NoEventSmallImagePortrait.png";
}
 
// is there EventSmallImageLandscape image
try
{
shows[i].EventSmallImageLandscape = (string) shows[i].Image.Descendants("EventSmallImageLandscape").ElementAt(0);
}
catch (ArgumentOutOfRangeException)
{
shows[i].EventSmallImageLandscape = "Images/NoEventSmallImageLandscape.png";
}
 
// is there EventLargeImagePortrait image
try
{
shows[i].EventLargeImagePortrait = (string) shows[i].Image.Descendants("EventLargeImagePortrait").ElementAt(0);
}
catch (ArgumentOutOfRangeException)
{
shows[i].EventLargeImagePortrait = "Images/NoEventLargeImagePortrait.png";
}
}
// store all Show objects to List (in App.xaml.cs file)
app.theatreShows.Add(shows);
// show is loaded
showsLoaded++;
// get another theatre shows (if there are any left)
if (showsLoaded < app.theatreAreas.Count()) GetSchedule();
// all shows are loaded, create menu of Theatres
else if (showsLoaded == app.theatreAreas.Count())
{
app.dataLoaded = true;
AddTheatres();
}
}
}

现在所有的大规模XML数据已经加载,是时候创建用户的主菜单了。在这个例子中,当应用程序申请返回此页时,只添加剧院名到该页面中的ListBox

public void AddTheatres()
{
// remove info textblock (displays loading information)
ContentPanel.Children.Remove(InfoTextBlock);
// remove previous names from the list
TheatreListBox.Items.Clear();
// create listbox items from theatreAreas
for (int i = 0; i < app.theatreAreas.Count(); i++)
{
TheatreListBox.Items.Add(app.theatreAreas[i].name);
}
// add eventlistener to listbox
TheatreListBox.SelectionChanged += new SelectionChangedEventHandler(TheatreListBox_SelectionChanged);
}

当用户从TheatreListBox选择剧院时,将会显示一个新的显示页。所有的数据都被存储到App类中,所以我们需要传递剧院的索引到新的页面。我们从列表清除SelectionChanged方法(当列表再次显示时它将再次被创建),最后通过用GET方法发送一个参数的方式打开了一个新的页面(这是在Windows Phone应用程序中页面间共享数据的一种方式)。

void TheatreListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// get the selected theatre index
int selectedIndex = (sender as ListBox).SelectedIndex;
// remove listener from the listbox
TheatreListBox.SelectionChanged -= new SelectionChangedEventHandler(TheatreListBox_SelectionChanged);
// open a shows page with selected index
this.NavigationService.Navigate(new Uri("/ShowsPage.xaml?SelectedIndex="+selectedIndex, UriKind.Relative));
}

ShowsPage

设计 (ShowsPage.xaml)

在你的项目中创建一个新的页面,右击Solution Explorer,并选择添加,新项... 在ShowsPage.xaml中选择Windows Phone Portrait Page并命名。

PTM FinnkinoAddShowsPage.png

ShowsPage的功能是在ListBox控件中显示并选择剧院的节目/电影。页面grid包含背景,标题和ListBox

<Grid x:Name="LayoutRoot">
<Grid.Background>
<ImageBrush ImageSource="Images/bg2.png"/>
</Grid.Background>
<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="FiNNKiNO - Kaupunki"
Foreground="White"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="elokuvat" Margin="9,-7,0,0"
Foreground="White"
Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
 
<!-- Shows ListBox Control -->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="ShowsListBox"
Foreground="White"
ItemTemplate="{StaticResource ShowDataTemplate}"/>
</Grid>
</Grid>

在这个例子中,处理背景图片就像早先所描述的一样。在这个页面中有趣的部分是ListBox以及它的属性ItemTemplate。 在Windows Phone编程中,你可以做一个模板并且在不同的页面中使用这些模板显示同样的信息。本文的原作者最先制作这个例子时使用Pivot Application应用程序模板,然后在不同的Pivots显示剧院的所有节目。然后,有超过15个不同的页面(pivots)显示在不同的剧院区的类似的列表(被迫创建模板以在ListBox中显示节目)。然后他将程序搬到了Panorama,因为pivots的内存管理(真的不需要在同一时间显示所有的剧院区节目,对不对?)。

ShowsDataTempate已经在 App.xaml中描述。在左侧有100像素的空间给图像,右侧使用TextBlock控件。数据被从ShowsPage类绑定到UI。

PTM FinnkinoShowsItem.png

<Application.Resources>
<DataTemplate x:Key="ShowDataTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Margin="5" BorderBrush="Black" BorderThickness="1">
<Image delay:LowProfileImageLoader.UriSource="{Binding EventSmallImagePortrait}" Width="65" Height="87"/>
</Border>
<StackPanel Grid.Column="1" Margin="5">
<TextBlock Text="{Binding Title}" FontSize="22" Foreground="White" />
<TextBlock Text="{Binding ShowStart}" FontSize="18" Foreground="White"/>
<TextBlock Text="{Binding TheatreAndAuditorium}" FontSize="18" Foreground="White"/>
<TextBlock Text="{Binding LengthInMinutes, StringFormat='\{0\} min'}" FontSize="18" Foreground="White" />
</StackPanel>
</Grid>
</DataTemplate>
</Application.Resources>

可以有100个图像被加载到页面中,这就是为什么我们使用PhonePerformance参考。记得在你的项目引用中加入引用到dll并且在你的App.xml文件下面使用XML命名空间。

xmlns:delay="clr-namespace:Delay;assembly=PhonePerformance"

编程(ShowsPage.xaml.cs)

当ShowsPage显示时,OnNavigatedTo方法将被调用。选择剧院索引可以在这个页面的NavigationContext中被找到。选择的剧院的数据在theatreAreastheatreShows列表中,这些列表在App.xaml类中。

App app = App.Current as App; // reference to App Class
int TheatreSelectedIndex; // selected Theatre Index
 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
 
// find Theatre's selected index (sent from ShowsPage.xaml)
IDictionary<string, string> parameters = this.NavigationContext.QueryString;
if (parameters.ContainsKey("SelectedIndex"))
{
// Theatre SelectedIndex (ListBox)
TheatreSelectedIndex = Int32.Parse(parameters["SelectedIndex"]);
// Show Selected Theatre name in Page Title
ApplicationTitle.Text = "Finnkino - " + app.theatreAreas[TheatreSelectedIndex].name;
// Bind data to ListBox (all events/shows in this theatre)
ShowsListBox.ItemsSource = app.theatreShows[TheatreSelectedIndex];
// Handle Selection of the ListBox
ShowsListBox.SelectionChanged += new SelectionChangedEventHandler(ShowsListBox_SelectionChanged);
}
}

当用户从ShowsListBox选择节目时,一个新的节目详细信息页面将被显示。选择的剧院和节目索引将作为一个GET方法被传递到这个新的类。

int selectedIndex = (sender as ListBox).SelectedIndex;
this.NavigationService.Navigate(new Uri("/ShowDetailPage.xaml?TheatreSelectedIndex=" + TheatreSelectedIndex+"&ShowSelectedIndex="+selectedIndex, UriKind.Relative));

ShowDetailPage

设计(ShowDetailPage.xaml)

要在你的项目中创建一个新的页面,在解决方案资源管理器右键单击你的项目,并选择添加,新项...选择Windows Phone纵向页面,并将它命名为ShowDetailPage.xaml。 这个ShowDetailPage显示选定电影的细节(见左图)。在设计模式中Grid包括页面的标题,图片和包含TextBlocks和按钮的基本信息。电影的简介文字显示在屏幕的底部(见右图)。

Movie details Movie details design page

在这个例子中节目详细信息页面的背景和标题做了如同前几页一样的处理。只有较小的文本字体被应用到标题。页面的主要内容则更加不同。 标题下面的图片和电影的详细信息(和按钮)的空间被分组到StaticPanel块(右侧图像)。

<Grid.ColumnDefinitions>
<ColumnDefinition Width="110"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image x:Name="Image"
Grid.Column="0"
Width="99"
Height="146"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Margin="6"/>
<StackPanel Margin="10,15,0,0" Grid.Column="1" Height="200" VerticalAlignment="Top">
<StackPanel Grid.Row="0" Height="120">
<TextBlock x:Name="ShowStart" FontSize="20" Foreground="White"/>
<TextBlock x:Name="LengthInMinutes" FontSize="20" Foreground="White" />
<TextBlock x:Name="Genres" FontSize="20" Foreground="White"/>
<TextBlock x:Name="ProductionYear" FontSize="20" Foreground="White"/>
</StackPanel>
<StackPanel Margin="0,0,0,0" Grid.Row="1" Height="70" VerticalAlignment="Top" HorizontalAlignment="Left" Orientation="Horizontal">
<Button Content="Osta liput" FontSize="20" Height="64" Width="160" BorderBrush="White" Foreground="White" Click="OstaLiput_Click"/>
<Button Content="Katso video" FontSize="20" Height="64" Width="160" BorderBrush="White" Foreground="White" x:Name="PlayVideo" Click="PlayVideo_Click"/>
</StackPanel>
</StackPanel>
</Grid>

电影的简介文字ScrollView显示在TextBlock中。

<Grid Height="480" VerticalAlignment="Top" Margin="0,200,0,0">
<ScrollViewer Height="400" Grid.ColumnSpan="2" Margin="0,0,0,0">
<TextBlock x:Name="Synopsis"
FontSize="20"
Foreground="White"
TextWrapping="Wrap"/>
</ScrollViewer>
</Grid>

编程(ShowDetailPage.xaml)

如同之前的页,当ShowDetailPage显示时OnNavigatedTo方法将被调用。我们在这里使用到ShowDetailPage类里面几个变量。

App app = App.Current as App;       // reference to App Class
MediaPlayerLauncher VideoLaucher; // used to display movie trailer
 
Show selectedShow; // selected Show object
string selectedVideo = ""; // video url of the selected Show object

OnNavigatedTo方法中, 选中的剧院和电影的索引是通过GET进行传递的。然后显示该影片的信息(开始时间,流派,年份和长度)。最后显示从theatreEvents名单中选定的节目的简介和video Url(根据IDs)。如果选定电影有预告片,创建一个新的MediaPlayerLauncher对象来显示。

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
 
IDictionary<string, string> parameters = this.NavigationContext.QueryString;
if (parameters.ContainsKey("TheatreSelectedIndex") && parameters.ContainsKey("ShowSelectedIndex"))
{
// Theatre SelectedIndex (ListBox)
int TheatreSelectedIndex = Int32.Parse(parameters["TheatreSelectedIndex"]);
ApplicationTitle.Text = "Finnkino - " + app.theatreAreas[TheatreSelectedIndex].name;
// selected show
int ShowSelectedIndex = Int32.Parse(parameters["ShowSelectedIndex"]);
selectedShow = (Show) app.theatreShows[TheatreSelectedIndex][ShowSelectedIndex];
PageTitle.Text = selectedShow.Title;
 
ShowStart.Text = "Alkaa kello: " + selectedShow.ShowStart;
Genres.Text = "Genre: " + selectedShow.Genres;
ProductionYear.Text = "Vuosi: " + selectedShow.ProductionYear;
LengthInMinutes.Text = "Kesto: " + selectedShow.LengthInMinutes + " min";
 
 
// find selected show -> event id
for (var i = 0; i < app.theatreEvents.Count(); i++)
{
if (app.theatreEvents[i].EventID == selectedShow.EventID)
{
// synopsis text
Synopsis.Text = app.theatreEvents[i].Synopsis;
// show video
if (app.theatreEvents[i].Video.Count() > 0)
{
selectedVideo = app.theatreEvents[i].Video.Descendants("Location").ElementAt(0).Value;
}
break;
}
}
 
// small image
Image.Source = new BitmapImage(new Uri(selectedShow.EventLargeImagePortrait, UriKind.RelativeOrAbsolute));
 
if (selectedVideo != "")
{
VideoLaucher = new MediaPlayerLauncher();
}
else
{
PlayVideo.IsEnabled = false;
}
 
}
}

这个类有两个buttons,这些Button的事件处理程序是最后的编程部分。 当用户点击"Osta liput" Button时, Windows Phone的默认浏览器将被使用。

Finnkino Web Page

private void OstaLiput_Click(object sender, RoutedEventArgs e)
{
WebBrowserTask webbrowser = new WebBrowserTask();
webbrowser.Uri = new Uri(selectedShow.ShowURL);
webbrowser.Show();
}

当用户点击"Katso video" Button时,Windows Phone的默认视频播放器将被使用。

Movie Trailer in FullScreen

private void PlayVideo_Click(object sender, RoutedEventArgs e)
{
VideoLaucher.Controls = MediaPlaybackControls.All;
VideoLaucher.Location = MediaLocationType.Install;
VideoLaucher.Media = new Uri(selectedVideo, UriKind.Absolute);
VideoLaucher.Show();
}

处理墓碑模式

就像之前写的,Windows Phone是可以将你的应用程序扔进墓碑模式的,然后你只要存储应用程序数据并在应用程序再次运行时加载它就可以了。所有数据都存储在App类的List集合中。

public partial class App : Application
{
public List<TheatreArea> theatreAreas; // Theatre Areas
public List<Event> theatreEvents; // Theatre Events
public List<List<Show>> theatreShows = new List<List<Show>>(); // Theatre Shows
public bool dataLoaded; // is data loaded from Finnkino's server
...
}

App类中有Application_Launching, Application_ActivatedApplication_Deactivated等方法,它们将由系统自动调用。

Application_Launching方法

只有当应用程序正在启动时,Application_Launching方法才会被调用,当应用程序再次被重新激活时,它不会被再次执行。这里初始化dataLoaded变量为false。

private void Application_Launching(object sender, LaunchingEventArgs e)
{
dataLoaded = false;
}

Application_Activated方法

当应用程序被激活(运行在前台),Application_Activated方法将被调用。在这里第一次检查应用程序是处于休眠或墓碑模式状态。如果检测到应用程序处于墓碑状态,那么所有的应用数据将加载List集合中。

private void Application_Activated(object sender, ActivatedEventArgs e)
{
if (e.IsApplicationInstancePreserved)
{
// DORMANT
}
else
{
// TOMBSTONED
if (PhoneApplicationService.Current.State.ContainsKey("TheatreAreas"))
{
theatreAreas = (List<TheatreArea>)PhoneApplicationService.Current.State["TheatreAreas"];
}
 
if (PhoneApplicationService.Current.State.ContainsKey("TheatreEvents"))
{
theatreEvents = (List<Event>)PhoneApplicationService.Current.State["TheatreEvents"];
}
 
if (PhoneApplicationService.Current.State.ContainsKey("TheatreShows"))
{
theatreShows = (List<List<Show>>)PhoneApplicationService.Current.State["TheatreShows"];
}
}
dataLoaded = true;
}

Application_Deactivated方法

当应用程序时关闭(扔到后台)Application_Deactivated将执行。在这里将List集中的数据保存到手机内存中。

private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
if (!PhoneApplicationService.Current.State.ContainsKey("TheatreAreas"))
PhoneApplicationService.Current.State.Add("TheatreAreas", theatreAreas);
if (!PhoneApplicationService.Current.State.ContainsKey("TheatreEvents"))
PhoneApplicationService.Current.State.Add("TheatreEvents", theatreEvents);
if (!PhoneApplicationService.Current.State.ContainsKey("TheatreShows"))
PhoneApplicationService.Current.State.Add("TheatreShows", theatreShows);
}

在Windows Phone模拟器上测试墓碑模式

在真正的手机上测试墓碑模式是非常困难的,但你可以在Windows Phone模拟器上测试,这样比较容易。右击你项目中的Solutions Explorer 并选择属性,选择Debug,并选择Tombstone upon deactivation while debugging。

PTM FinnKinoDebugTombstone.png

现在你的Finnkino Elokuvat应用程序在模拟器运行,并等待它加载Finnkino的服务器上的所有数据。当Finnkino Elokuvat应用程序中的任何页面显示时点击模拟器上的Windows Button。现在Finnkino Elokuvat应用程序将被扔到后台((Application_Deactivated将被调用来将数据保存到设备)并将所有的数据从内存中删除。浏览器返到回Finnkino Elokuvat应用程序后,Application_Activated方法将被调用来将剧院所有的数据加载到内存。

应用程序测试

在发布到Windows市场之前,最好测试你的应用程序。你可以在Visual Studio中打开和运行Marketplace Test Kit,但是你必须将你的应用程序设置为Release模式。

PTM FinnKinoTestRelease01.png

选择项目,然后从主菜单中选择Open Marketplace Test Kit。

PTM FinnKinoTestRelease02.png

首先,你必须添加更多的资源来运行这些测试。基本上时Marketplace上要求大小不同的图像。从Test Kit中选择第二个选项卡,你可以运行自动化测试。它会返回你的的XAP文件信息,使用的功能,还有你的图标和屏幕截图尺寸是否正确。

PTM FinnKinoTestRelease03.png

PTM FinnKinoTestRelease04.png

Monitored test是用来分析应用程序的性能和功能的。你必须先启动你的应用程序,在应用程序中的进行前进和后退导航,最后关闭应用程序,以生成测试数据。你应该运行在真实的设备以得到真正的考验。

在Marketplace Test Kit中也有很多不同的手动测试,它们对测试来说都是有效的。

总结

这是本文原作者写过最长的的文章之一。希望这些文章对你有用,并可以帮助你在WP7中使用XML。 你可以在下面的网站中获得原代码:File:PTMFinnkinoElokuvat.zip 这个应用程序也可以从Windows Marketplace获得:Finnkino Elokuvat

This page was last modified on 19 July 2013, at 07:38.
310 page views in the last 30 days.
×