65.9K
CodeProject 正在变化。 阅读更多。
Home

了解各地 (LAP)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2013年8月22日

CPOL

5分钟阅读

viewsIcon

8781

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 上的第一篇帖子。

© . All rights reserved.