本文的样例来自于Windows-universal-samples的XamlListView。

这个样例中其实包含了很多示例:

  • Simple ListView
  • Simple GridView
  • Master Detail and Selection
  • Edge Tapped ListView
  • Restore Scroll Position Sample
  • Scroll Into View

上面的这些示例每个对应一个XAML页面。有一个针对所有示例的导航是列举在一个SplitView的Panel里面。为了让这个SplitView的Panel可以在不同的XAML页面访问,这个SplitView被做成了一个UserControl,放在SamplesPane.xaml中,在每个示例的XAML页面中包含下面一段来引用这个SamplesPane.xaml:

        <local:SamplesPane x:Name="MySamplesPane" Grid.ColumnSpan="2" Grid.RowSpan="2" />

所有示例的页面布局都是差不多的都采用两行两列的Grid,首行首列的格子用来放菜单键,用来触发SamplesPane.xaml,代码如下:

        private void ShowSplitView(object sender, RoutedEventArgs e)
        {
            MySamplesPane.SamplesSplitView.IsPaneOpen = !MySamplesPane.SamplesSplitView.IsPaneOpen;
        }

菜单键是一个Button:

        <Button Style="{StaticResource SplitViewTogglePaneButtonStyle}"
                Click="ShowSplitView"/>

其显示的内容为是在SplitViewTogglePaneButtonStyle中定义的:

                <Setter Property="Content" Value="&#xE700;" />

上面的&#xE700;是一个Unicode字符,形状是三条横线的汉堡包。

在SamplesPane.xaml.cs中,通过下面的代码来导航到不同的示例页面。

...
       private void NavigateToOptimized(object sender, RoutedEventArgs e)
        {
            ((Frame)Window.Current.Content).Navigate(typeof(SimpleListViewSample));
        }
        private void NavigateToOptimizedGrid(object sender, RoutedEventArgs e)
        {
            ((Frame)Window.Current.Content).Navigate(typeof(SimpleGridViewSample));
        }
...

SimpleListViewSample

SimpleListViewSample这个示例的数据是来自

        <CollectionViewSource x:Name="ContactsCVS"  IsSourceGrouped="True" />

CollectionViewSource 会在SimpleListViewSample背靠类的构造函数中填充内容:

            ContactsCVS.Source = Contact.GetContactsGrouped(250);

上面的GetContactsGrouped来自Model.Contacs.cs,其中生成分组的代码片段如下:

            var query = from item in GetContacts(numberOfContacts)
                        group item by item.LastName.Substring(0, 1).ToUpper() into g
                        orderby g.Key
                        select new { GroupName = g.Key, Items = g };

ListView的ListViewItem是通过DataTemplate来指定其显示形式的:

        <DataTemplate x:Name="ContactListViewTemplate" x:DataType="data:Contact">

DataTemplate包含一个Grid,两行两列。其中左边两列显示一个椭圆,右边首列是名字,右边第二列是职位。

ListView可以指定GroupStyle,本例中GroupStyle比较简单,就是一个含有TextBlock 的DataTemplate

            <ListView.GroupStyle>
                <GroupStyle >
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate x:DataType="data:GroupInfoList">
                            <TextBlock Text="{x:Bind Key}" 
                                       Style="{ThemeResource TitleTextBlockStyle}"/>
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ListView.GroupStyle>

可以看到上面的GroupStyle的DataTemplate通过x:DataType="data:GroupInfoList"指定了其类型为GroupInfoList,这个类型的定义如下:

    public class GroupInfoList : List<object>
    {
        public object Key { get; set; }
    }

其他知识点

x:Phase attribute可以用来控制在滚动的时候ListView中那些细节会优先显示。默认情况下,ListItemTemplate中的所有细节都是x:Phase=0,如果将x:Phase置成1,则会在x:Phase=0之后显示.

如果一个XAML元素使用x:Name指定了名字,那么它就会成为其背靠类的一个属性。比如ContactListViewTemplate就会出现在SimpleListViewSample.g.i.cs中(此文件是XAML解析过程中生成的)。默认情况下,这个属性的访问特性为private,但是可以通过指定x:FieldModifier来将其声明为public。

XAML中可以通过下面的注释来创建折叠区域:

        <!--#region Navigation Panel -->
        <!--#endregion-->

可以通过下面的方式来访问打包到应用内的资源:

                new BitmapImage(new Uri("ms-appx:///Assets/sunset.jpg"))

C#语言的static字段竟然可以在构造函数中初始化,就像此例Item.sources在Item()中初始化一样。

C#语言的namespace可以在定义的时候用点号隔开:namespace ListViewSample.Model

其他参考