了解各地 (LAP)





5.00/5 (2投票s)
LAP 提供了一个功能丰富的环境,用于学习和欣赏全球各地历史和地理。
引言
人们在阅读和学习地球上不同地方的历史和地理时,这常常是一项繁琐的工作。整天阅读厚重的书籍,学习这些科目毫无乐趣。我自己就曾体验过将热情投入到学习这些科目中的必要性,因为你知道过去的知识对于未来的改进很重要。
好了,这个问题已经被“了解地点 (LAP)”解决了。LAP 通过在地图上图形化地展示不同地点、这些地点的历史以及地理位置来解决这些问题。在学习了相关地点的历史和地理后,用户可以进行测验来检查他们的学习成果。现在,让我们深入了解该应用程序的详细描述,展示它是如何工作的,以及它如何造福目标用户。
类别和平台
LAP 是一款具有学习知识的娱乐应用程序。使其成为娱乐应用程序的元素是其巧妙地使用了必应地图 (Bing Maps)、探索性文章,以及通过包括测验在内的有趣游戏来检验你的知识。因此,LAP 是一个完整的娱乐套餐。
LAP 针对的平台是 ALL-In-One PC。这一新类别的设备所提供的功能可以增强和探索应用程序的功能。联想 Horizon 一体机 (All-In-One PC) 的功能,例如 Aura 界面,可以为用户扩展应用程序体验。
概述
现在我们已经谈了足够多的关于 LAP 的功能,从现在开始,让我们深入了解该应用程序的详细描述。
该应用程序主要(在某种程度上)分为四个类别
(a)。地点的历史。
(b)。地点的地理。
(c)。趣味游戏。
(d)。测验。
这三个大类在应用程序中并非严格按顺序排列,因为用户在使用应用程序时,应用程序的流程会管理这些方面。现在让我们看看主页的截图。
LAP 的 GUI(图形用户界面)非常简单,没有华丽的装饰。上面显示的主页仅包含两个选项。一个是“输入地点”,另一个是“计划一次学习之旅”,并对这两个选项进行了简要描述。
LAP 的工作原理
输入地点
“输入地点”会将用户导航到一个面板,在那里他们可以输入需要了解历史和地理的地点。输入的地点将在地图上突出显示,并显示一些详细信息,同时在面板的右侧显示该特定地点的历史、地理和游戏选项。
计划一次学习之旅
“计划一次学习之旅”比另一个选项更高级一些。它真正探索并包含了应用程序的所有组件。用户会导航到一个面板,在那里他们输入两个地点,类似于在地图上查找两个地点之间的路径。这两个地点之间的路径会显示在地图上,并沿路径突出显示一系列地点。现在,用户从起点开始,沿着路径旅行,探索沿途这些地点的历史和地理。因此得名“计划一次学习之旅”。
应用程序功能
以上是 LAP 提供的基本功能。现在,让我们深入了解该应用程序的细节。 输入地点后,它们对应的名称会以列表的形式显示在右侧的面板中,如上文两个选项所示。
对于两个选项,请从列表中选择一个地点。这将导航到一个新页面,列出上面所示的分类。
选择以上任一选项。
1. 历史
选择此选项后,用户将被导航到一个新页面,其中包含与该地点历史相关的文章、视频和书籍。文章可能来自任何作者。视频包括来自不同来源的历史系列片段,例如历史频道。书籍由不同作者撰写,与该地点的历史有关。
2. 地理
选择此选项后,用户将被导航到一个新页面,其中包含该地点的地理信息列表,例如经度、纬度、大陆、国家、州、城市等。除了这些详细信息外,还可以选择视频、文章和该地点的历史选项。此外,还可以提供一张地图截图,标示出地图上的地理位置。
3. 测验
选择测验选项后,用户将被导航到一个新页面,其中包含历史和地理问题。用户可以参加测验,并会获得测验分数。这能在用户之间产生竞争。
4. 游戏
选择此选项后,用户将被导航到一个新页面,其中包含一系列有趣的益智游戏。
开发 LAP
概述
LAP 是使用 Microsoft Visual Studio 2012 开发的。Metro 应用在联想 Horizon AIO 上作为桌面应用运行,因此 LAP 也一样。LAP 的设计是在 VS2012 编辑器中使用 XAML(可扩展应用程序标记语言)完成的。XAML 对于设计 Windows 应用程序非常方便。LAP 的逻辑是用 C# 编程语言编写的。
设计
LAP 的设计和架构经过精心设计。任何元素之间的松散耦合都被省略了。这种耦合被移除是因为使用了 MVVM(模型-视图-视图模型)方法来开发 LAP。
LAP 使用必应地图 (Bing Maps),因此使用必应地图 API 来包含地图元素。应用程序的启动页面打开时会显示一个地图,上面有两个选项,如“LAP 的工作原理”部分所述。 LAP 的启动页面代码如下。
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Maps:Map x:Name="BingMap"
HomeRegion="US" Culture="en-US"
Credentials="{StaticResource BingCredentials}"/>
<Grid Background="#FFF5810D" Margin="134,40,475,52">
<Grid.RowDefinitions>
<RowDefinition Height="127*"/>
<RowDefinition Height="641*"/>
</Grid.RowDefinitions>
<TextBlock HorizontalAlignment="Left"
Margin="45,42,0,0" TextWrapping="Wrap"
VerticalAlignment="Top" FontSize="50">
<Underline>Categories</Underline>
</TextBlock>
<Grid Grid.Row="1" Background="#FFF7E209">
<Button Content="History" HorizontalAlignment="Left"
Margin="97,83,0,0" VerticalAlignment="Top"
Height="152" Width="200" FontSize="30"
Background="#FFB4B429"/>
<Button Content="Games" HorizontalAlignment="Left"
Margin="97,284,0,0" VerticalAlignment="Top"
Width="200" Height="152" FontSize="30"
Background="#FFB4B429"/>
<Button Content="Geography" HorizontalAlignment="Left"
Margin="404,83,0,0" VerticalAlignment="Top"
Height="152" Width="200" FontSize="30"
Background="#FFB4B429"/>
<Button Content="Quiz" HorizontalAlignment="Left"
Margin="404,284,0,0" VerticalAlignment="Top"
Height="152" Width="200" FontSize="30"
Background="#FFB4B429"/>
</Grid>
</Grid>
<StackPanel x:Name="_MainStackPanel"
HorizontalAlignment="Left" Height="768"
VerticalAlignment="Top" Width="337"
Margin="1029,0,0,0" Background="#FFD8A840">
<Button Content="Enter a Place" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Margin="5,20,5,5"
Background="#FFDE6B35" Height="52"
FontSize="20" Click="Enter_Place_Event_Click"/>
<Button Content="Plan a learning Trip"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Margin="5,5,5,5"
Background="#FFDE6B35" Height="52" FontSize="20"/>
<TextBlock TextWrapping="Wrap" FontSize="22" Margin="12,20,0,0">
<Underline>Places:</Underline>
</TextBlock>
<TextBlock Margin="12,15,5,5" FontSize="17" TextWrapping="Wrap">
<Underline FontSize="20">Enter a Place:</Underline>
Click on the button, a panel opens where you enter a place to explore and learn about it
<LineBreak/>
<LineBreak/>
<Underline FontSize="20">Plan a Learning Trip</Underline>
Click on the button, a panel opens where you enter two places.
The places between these places including them are their
present for exploration
</TextBlock>
</StackPanel>
</Grid>
历史页面设计代码,列出文章、视频和书籍。
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.RowSpan="2"
Padding="116,137,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemTemplate="{StaticResource Standard250x250ItemTemplate}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="1,0,0,6">
<Button
AutomationProperties.Name="Group Title"
Click="Header_Click"
Style="{StaticResource TextPrimaryButtonStyle}" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" Margin="3,-7,10,10"
Style="{StaticResource GroupHeaderTextStyle}" />
<TextBlock Text="{StaticResource ChevronGlyph}"
FontFamily="Segoe UI Symbol" Margin="0,-7,0,10"
Style="{StaticResource GroupHeaderTextStyle}"/>
</StackPanel>
</Button>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical"
Margin="0,0,80,0"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
<ListView
x:Name="itemListView"
AutomationProperties.AutomationId="ItemListView"
AutomationProperties.Name="Grouped Items"
Grid.Row="1"
Visibility="Collapsed"
Margin="0,-10,0,0"
Padding="10,0,0,60"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
ItemTemplate="{StaticResource Standard80ItemTemplate}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="7,7,0,0">
<Button
AutomationProperties.Name="Group Title"
Click="Header_Click"
Style="{StaticResource TextPrimaryButtonStyle}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" Margin="3,-7,10,10"
Style="{StaticResource GroupHeaderTextStyle}" />
<TextBlock Text="{StaticResource ChevronGlyph}"
FontFamily="Segoe UI Symbol" Margin="0,-7,0,10"
Style="{StaticResource GroupHeaderTextStyle}"/>
</StackPanel>
</Button>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack"
IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}"
Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Text="{StaticResource AppName}"
Grid.Column="1" IsHitTestVisible="false"
Style="{StaticResource PageHeaderTextStyle}"/>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="backButton"
Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource PortraitBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView"
Storyboard.TargetProperty="Padding">
<DiscreteObjectKeyFrame KeyTime="0" Value="96,137,10,56"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="backButton"
Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle"
Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
类别 UI XAML 代码,显示不同的分类。
<Grid Background="#FFF5810D" Margin="134,40,475,52">
<Grid.RowDefinitions>
<RowDefinition Height="127*"/>
<RowDefinition Height="641*"/>
</Grid.RowDefinitions>
<TextBlock HorizontalAlignment="Left" Margin="45,42,0,0" TextWrapping="Wrap"
VerticalAlignment="Top" FontSize="50">
<Underline>Categories</Underline>
</TextBlock>
<Grid Grid.Row="1" Background="#FFF7E209">
<Button Content="History" HorizontalAlignment="Left" Margin="97,83,0,0"
VerticalAlignment="Top" Height="152" Width="200"
FontSize="30" Background="#FFB4B429"/>
<Button Content="Games" HorizontalAlignment="Left"
Margin="97,284,0,0" VerticalAlignment="Top" Width="200"
Height="152" FontSize="30" Background="#FFB4B429"/>
<Button Content="Geography" HorizontalAlignment="Left"
Margin="404,83,0,0" VerticalAlignment="Top"
Height="152" Width="200" FontSize="30"
Background="#FFB4B429"/>
<Button Content="Quiz" HorizontalAlignment="Left"
Margin="404,284,0,0" VerticalAlignment="Top"
Height="152" Width="200" FontSize="30"
Background="#FFB4B429"/>
</Grid>
</Grid>
代码
代码隐藏文件处理应用程序的业务逻辑。C# 编程语言用于编写应用程序的业务逻辑。在开发 LAP 时,使用了必应地图 SDK,因此将其引用添加到项目中。使用了必应地图 REST 服务及其路由和位置 API 来查找路径和相应的位置。
以下是启动页面代码隐藏文件。
private async Task<BingMapsRESTService.Response> GetResponse(Uri uri)
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var response = await client.GetAsync(uri);
using (var stream = await response.Content.ReadAsStreamAsync())
{
DataContractJsonSerializer ser =
new DataContractJsonSerializer(typeof(BingMapsRESTService.Response));
return ser.ReadObject(stream) as BingMapsRESTService.Response;
}
}
async private void Button_To_Search_Route_Click(object sender, RoutedEventArgs e)
{
Button_To_Search_Route.IsEnabled = false;
if (Text_For_From_Location.Text == "" || TextBox_To_Enter_To_Location.Text == "")
{
Popup_Notification(2);
}
else
{
try
{
ProgressBar.IsIndeterminate = true;
ProgressBar.Visibility = Visibility.Visible;
Canvas_To_Find_Route.Visibility = Visibility.Collapsed;
URL = "http://dev.virtualearth.net/REST/V1/Routes/Driving?o=json&wp.0=" +
TextBox_To_Enter_To_Location.Text + "&wp.1=" +
Text_For_From_Location.Text + "&optmz=distance&rpo=Points&key=" + map.Credentials;
Uri geocodeRequest = new Uri(URL);
BingMapsRESTService.Response r = await GetResponse(geocodeRequest);
geolocator = new Geolocator();
pushpin = new Pushpin();
FromLatitude = ((BingMapsRESTService.Route)(r.ResourceSets[0].Resources[0])).RoutePath.Line.Coordinates[0][0];
FromLongitude = ((BingMapsRESTService.Route)(r.ResourceSets[0].Resources[0])).RoutePath.Line.Coordinates[0][1];
location = new Bing.Maps.Location(FromLatitude, FromLongitude);
MapLayer.SetPosition(pushpin, location);
map.Children.Add(pushpin);
map.SetView(location, 8.0f);
MapPolyline routeLine = new MapPolyline();
routeLine.Locations = new LocationCollection();
routeLine.Color = Windows.UI.Colors.Red;
routeLine.Width = 5.0;
int bound = ((BingMapsRESTService.Route)(
r.ResourceSets[0].Resources[0])).RoutePath.Line.Coordinates.GetUpperBound(0);
for (int i = 0; i < bound; i++)
{
routeLine.Locations.Add(new Bing.Maps.Location
{
Latitude = ((BingMapsRESTService.Route)(
r.ResourceSets[0].Resources[0])).RoutePath.Line.Coordinates[i][0],
Longitude = ((BingMapsRESTService.Route)(
r.ResourceSets[0].Resources[0])).RoutePath.Line.Coordinates[i][1]
});
}
pushpin1 = new Pushpin();
location1 = new Bing.Maps.Location(routeLine.Locations[0]);
MapLayer.SetPosition(pushpin1, location1);
MapShapeLayer shapeLayer = new MapShapeLayer();
shapeLayer.Shapes.Add(routeLine);
map.ShapeLayers.Add(shapeLayer);
ProgressBar.IsIndeterminate = false;
ProgressBar.Visibility = Visibility.Collapsed;
Canvas_For_Searching_Location.Visibility = Visibility.Collapsed;
}
catch (Exception ex)
{
var dialog = new MessageDialog(ex.Message);
}
}
Button_To_Search_Route.IsEnabled = true;
}
async private void Button_To_Search_Location_Click(object sender, RoutedEventArgs e)
{
Button_To_Search_Location.IsEnabled = false;
if (TextBox_To_Enter_Location.Text == "")
{
Canvas_For_Searching_Location.Visibility = Visibility.Collapsed;
Popup_Notification(1);
}
else
{
try
{
Canvas_For_Searching_Location.Visibility = Visibility.Collapsed;
ProgressBar.IsIndeterminate = true;
ProgressBar.Visibility = Visibility.Visible;
URL = "http://dev.virtualearth.net/REST/V1/Routes/Driving?o=json&wp.0=" +
TextBox_To_Enter_Location.Text + "&wp.1=" +
TextBox_To_Enter_Location.Text +
"&optmz=distance&rpo=Points&key=" + map.Credentials;
string value = "Ar1AUldQavUnDzLKSQtJ-9evD7v8uA-v6ZdJNpCx7Swkuxif5X1l7FPbx6v";
GeocodeRequest geocoderequest = new GeocodeRequest();
geocoderequest.Credentials = new WowZapp_Application.Geocode_Service.Credentials();
geocoderequest.Credentials.ApplicationId = value;
geocoderequest.Query = TextBox_To_Enter_Location.Text;
ConfidenceFilter[] filters = new ConfidenceFilter[1];
filters[0] = new ConfidenceFilter();
filters[0].MinimumConfidence = WowZapp_Application.Geocode_Service.Confidence.High;
GeocodeServiceClient geocodeservice = new GeocodeServiceClient(
GeocodeServiceClient.EndpointConfiguration.BasicHttpBinding_IGeocodeService);
GeocodeResponse geocoderesponse = await geocodeservice.GeocodeAsync(geocoderequest);
if (geocoderesponse.Results.Count > 0)
{
Bing.Maps.Location location = new Bing.Maps.Location(
geocoderesponse.Results[0].Locations[0].Latitude,
geocoderesponse.Results[0].Locations[0].Longitude);
MapLayer.SetPosition(pushpin1, location);
map.SetView(location, 10.0f);
ProgressBar.IsIndeterminate = false;
ProgressBar.Visibility = Visibility.Collapsed;
}
}
catch (Exception ex)
{
var dialog = new MessageDialog(ex.Message);
}
}
Button_To_Search_Location.IsEnabled = true;
}
目标用户
LAP 是一款全球性应用程序,任何用户都可以使用。但 LAP 应用程序更具针对性的用户是学生、教授、历史学家、地质学家,当然还有任何想享受学习的普通人。
历史
这是我在 CodeProject 上的第一篇帖子。