• 使用Windows8开发Metro风格应用四


    我们紧接着上篇,开始我们的Metro风格应用开发。

    -----------------------------------我是华丽的分割线-----------------------------------------

    12.在 XAML 中定义应用布局
       a)在接下来的在 XAML 中定义应用布局、添加控件和内容和显示数据 3 个部分中,
          我们将学习在 XAML 中创建用户界面的基本知识。为了学习这些基本知识,我们创建了一个简单的单页博客阅读器,
          以显示单个博客信息提要的文章。如果你已经有使用 XAML 的经验并且熟悉 XAML 布局、控件和数据绑定,
          则可以跳过这些部分且不用完成练习。但不要跳过为日期转换器添加代码的部分,稍后在我们的应用中会用到它。
          让我们回到添加页面和导航部分中的创建完整的 Metro 风格应用。
       b)应用布局用于指定应用中每个对象的大小和位置。要定位视觉对象,你必须将其置于某个Panel控件或其他容器对象中。
          XAML 布局系统提供了各种 Panel 控件,例如用作你在其中排列控件的 Grid、Canvas 和 StackPanel。
          XAML 布局系统既支持绝对布局,也支持动态布局。在绝对布局中,使用显式的 x 和 y 坐标(例如,使用 Canvas)来定位控件。
          在动态布局中,当应用重新调整大小时,布局容器和控件会随之自动改变大小和位置(例如使用StackPanel或Grid的情况)。
          在实际过程中,通常通过结合使用绝对布局和动态布局的方式,以及将面板嵌入到其他面板的方式来定义应用的布局。
          博客阅读器应用的典型布局如下:顶部为标题,左侧是文章列表,右侧是所选文章的内容。
       c)默认情况下,空白应用模板仅包含一个空白 Grid,它是我们的 UI 的根元素。为了指定我们的布局,我们将Grid划分为两行。
          首行显示博客标题。在第二行中,我们嵌入另一个Grid,将它分为两列,然后添加其他一些布局容器以显示博客内容。
       d)代码如下:

    View Code
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="140" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
    
            <!-- Title -->
            <TextBlock x:Name="TitleText" Text="{Binding Title}"
                       VerticalAlignment="Center" FontSize="48" Margin="56,0,0,0"/>
    
            <!-- Content -->
            <Grid Grid.Row="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="2*" MinWidth="320" />
                    <ColumnDefinition Width="3*" />
                </Grid.ColumnDefinitions>
    
                <!-- Left column -->
                <!-- The default value of Grid.Column is 0, so we do not need to set it   
                     to make the ListView show up in the first column. -->
                <ListView x:Name="ItemListView"  
                    ItemsSource="{Binding Items}"
                    Margin="60,0,0,10"
                    SelectionChanged="ItemListView_SelectionChanged">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock Text="{Binding Title}"  
                               FontSize="24" Margin="5,0,0,0" TextWrapping="Wrap" />
                                <TextBlock Text="{Binding Author}" 
                               FontSize="16" Margin="15,0,0,0"/>
                                <TextBlock Text="{Binding PubDate,Converter={StaticResource dateConverter}}" 
                               FontSize="16" Margin="15,0,0,0"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
    
                <!-- Right column -->
                <!-- We use a Grid here instead of a StackPanel so that the WebView sizes correctly. -->
                <Grid DataContext="{Binding ElementName=ItemListView, Path=SelectedItem}"
                      Grid.Column="1" Margin="25,0,0,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <TextBlock x:Name="PostTitleText" Text="{Binding Title}" FontSize="24"/>
                    <WebView x:Name="ContentView" Grid.Row="1" Margin="0,5,20,20"/>
                </Grid>
            </Grid>
        </Grid>


          我们更详细地看看此 XAML 可以做什么。若要在 Grid 中定义行,你需要在 Grid.RowDefinitions 集合中添加 RowDefinition 对象。
          你可以在 RowDefinition 中设置属性,以指定行的外观。添加列的方法是相同的,
          只不过要使用 ColumnDefinition 对象和 Grid.ColumnDefinitions 集合。第一个行定义(行 0)上的 Height="140" 属性设置
          将顶部的行设置为 140 个与设备无关的像素的绝对高度。无论行的内容或应用的大小如何变化,此高度都不会改变。
          第二个行定义(行 1)上的 Height="*" 设置告诉底部行占用行 0 占用后的所有空间。这通常称为星形比例缩放。
          我们在第二个Grid的列定义中也使用了比例缩放。宽度设置Width="2*"和Width="3*"要求Grid将自身分为 5 个相等的部分。
          两个部分用于第一列,三个部分用于第二列。要在Grid中定位某个元素,你需要设置该元素的附加属性Grid.Row和 Grid.Column。
          行和列编号是从零开始的。这些属性的默认值是 0,因此如果未设置任何内容,则该元素将位于第一行第一列。
          <Grid Grid.Row="1"> 元素在根 Grid 的底部行嵌入一个 Grid。该Grid被划分为两列。元素<ListView x:Name="ItemListView">
          将一个ListView添加到底部的左侧列中Grid。元素<Grid Grid.Column="1">将另一个Grid添加到底部的右侧列中Grid。
          我们将该Grid划分为两行。设置Height="Auto"要求顶行尽可能地调整高度以适合其内容。底行则占用剩下的所有空间。
       e)我们的 UI 中需要布局面板的最后一个部分是博客文章列表。
          在该列表中,我们需要按如下所示排列标题、作者和日期。
          当你需要在页面 UI 的一个小的子部分中自动排列连续元素时,通常使用一个 StackPanel。 
          StackPanel是一种简单的布局面板,可以将子元素按水平或垂直方向排列到单行中。
          你可以使用StackPanel.Orientation属性来指定子元素的方向。 Orientation属性的默认值是 Orientation.Vertical。
          我们使用StackPanel来排列博客文章列表中的项。我们看到在使用模板设置数据格式会用到它。
          StackPanel 的 XAML 如下:
            <StackPanel>
               <TextBlock Text="{Binding Path=Title}" FontSize="24" Margin="5,0,0,0" TextWrapping="Wrap" />
               <TextBlock Text="{Binding Path=Author}" FontSize="16" Margin="15,0,0,0"/>
               <TextBlock Text="{Binding Path=PubDate}" FontSize="16" Margin="15,0,0,0"/>
            </StackPanel>

    13.添加控件和内容
       通过添加按钮、列表、文本、图形和图像等控件创建应用的 UI。你所使用的元素取决于你的应用要完成的功能。
       我们需要显示一行文本(博客和文章标题)、多行文本(文章内容)和博客文章列表。我们通过添加TextBlock控件以显示标题,
       并且用一个ListView控件来显示博客文章列表。初看之下,我们似乎可以使用一个多行的TextBlock或RichTextBlock来显示文章内容。
       但是,当我们更深入了解时,我们发现包含文章内容的字符串不是纯文本,而是 HTML 字符串。我们不想显示一堆 HTML 标记,
       但如果我们将字符串放在一个 TextBlock 中便会发生这种情况,因此我们使用 WebView 控件来显示 HTML。
      Xmal代码请参看12中的代码。

    14.显示数据
       a)使用值转换器设置数据格式
          在 ItemListView 的DataTemplate中,我们将PubDate属性(是一个DateTime )绑定到TextBlock.Text属性。
          绑定引擎会自动将 PubDate 从一个 DateTime 转换为一个字符串。但自动转换会同时显示日期和时间,
          而我们只想显示日期。要修复此问题,我们可以创建自己的值转换器来将DateTime转换为字符串,
          并且可以在其中将字符串设置为任何需要的格式。要创建值转换器,我们先创建一个用于实现IValueConverter接口的类,
          然后实现Convert和ConvertBack方法。转换器可以将数据从一种类型更改为另一种类型,根据文化背景转换数据,
          或者修改数据呈现方式的其他方面。在这里,我们创建一个日期转换器,它将转换传入的日期值并设置其格式,从而只显示日、月和年。
       b)向项目添加值转换器类,请选择“项目”>“添加类”。将类命名为 DateConverter(.cs 或 .vb)。
          Convert和ConvertBack方法还允许你传入一个参数,以便通过不同的选项使用该转换器的同一个实例。
          在此示例中,我们包含了一个格式设置转换器,它可以根据输入的参数生成不同格式的日期。
          你可以使用Binding类的ConverterParameter向Convert和ConvertBack方法中传递一个参数。代码如下:
      

    View Code
       public class DateConverter:IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, string language)
            {
                if (value == null)
                    throw new ArgumentNullException("value", "Value cannot be null.");
    
                if (!typeof(DateTime).Equals(value.GetType()))
                    throw new ArgumentException("Value must be of type DateTime.", "value");
    
                DateTime dt = (DateTime)value;
    
                if (parameter == null)
                {
                    // Date "7/27/2011 9:30:59 AM" returns "7/27/2011"
                    return DateTimeFormatter.ShortDate.Format(dt);
                }
                else if ((string)parameter == "day")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "27"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{day.integer(2)}");
                    return dateFormatter.Format(dt);
                }
                else if ((string)parameter == "month")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "JUL"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{month.abbreviated(3)}");
                    return dateFormatter.Format(dt).ToUpper();
                }
                else if ((string)parameter == "year")
                {
                    // Date "7/27/2011 9:30:59 AM" returns "2011"
                    DateTimeFormatter dateFormatter = new DateTimeFormatter("{year.full}");
                    return dateFormatter.Format(dt);
                }
                else
                {
                    // Requested format is unknown. Return in the original format.
                    return dt.ToString();
                }
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, string language)
            {
                string strValue = value as string;
                DateTime resultDateTime;
                if (DateTime.TryParse(strValue, out resultDateTime))
                {
                    return resultDateTime;
                }
                return Windows.UI.Xaml.DependencyProperty.UnsetValue;
            }
        }

       c)使用 DateConverter 类之前,必须在我们的 XAML 中声明一个该类的实例。
          我们将关键字 dateConverter 作为 App.xaml 中应用资源来声明实例。在此处声明实例后,在应用的每个页面都可以使用它。
          代码如下:
            <Application.Resources>
               <ResourceDictionary>
                  <ResourceDictionary.MergedDictionaries>

                     <!-- 
                      Styles that define common aspects of the platform look and feel
                      Required by Visual Studio project and item templates
                      -->
                     <ResourceDictionary Source="Common/StandardStyles.xaml">
                     </ResourceDictionary>
                  </ResourceDictionary.MergedDictionaries>
                <local:FeedDataSource x:Key="feedDataSource"/>
                <local:DateConverter x:Key="dateConverter"/>
             </ResourceDictionary>
          </Application.Resources>
     
       d)现在,我们便可在绑定中使用 DateConverter 了。以下是来自 ItemListView 的 DataTemplate 中更新后的 PubDate 绑定。
            <TextBlock Text="{Binding PubDate,Converter={StaticResource dateConverter}}" FontSize="16" Margin="15,0,0,0"/>
    15.在 WebView 中显示 HTML
       WebView 控件为我们提供了一种在应用内承载 HTML 数据的方法。但如果我们看看它的 Source 属性,
       就会发现它采用 Web 页面的 Uri 进行显示。我们的 HTML 数据只不过是HTML 的字符串。它没有包含可以绑定到 Source 属性的 Uri。
       幸运的是,我们可以通过一种 NavigateToString 方法来传递我们的 HTML 字符串。
       要实现该功能,我们需要处理ListView的SelectionChanged事件。
      代码如下:
      

    View Code
     private void ItemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                FeedItem feedItem = e.AddedItems[0] as FeedItem;
                if (feedItem!=null)
                {
                    ContentView.NavigateToString(feedItem.Content);
                }
            }

    16.现在我们的博客浏览器已基本成型,如下是界面截屏:





    未完待续,敬请期待...

  • 相关阅读:
    无须任何软件配置iis+ftp服务器图文说明
    适合wordpress中文网站的seo优化插件 DX-Seo
    wordpress自动批量定时发布插件 DX-auto-publish
    wordpress自动保存远程图片插件 DX-auto-save-images
    wordpress图片水印插件DX-Watermark
    WordPress添加固定位置的百度分享按钮
    Ecshop 最小起订量如何设置
    WP主题制作常用标签代码
    ecshop登陆后价格可见,会员注册登陆才能显示价格
    ECshop设置301最快捷最简单的方法
  • 原文地址:https://www.cnblogs.com/refactor/p/2532762.html
Copyright © 2020-2023  润新知