• 重新想象 Windows 8.1 Store Apps (93)


    [源码下载]


    重新想象 Windows 8.1 Store Apps (93) - 控件增强: GridView, ListView



    作者:webabcd


    介绍
    重新想象 Windows 8.1 Store Apps 之控件增强

    • GridView 和 ListView 每屏显示的数据量多滚动也流畅
    • GridViewItemPresenter 和 ListViewItemPresenter 更方便更快速地显示各种状态
    • 自定义 GridViewItemPresenter 和 ListViewItemPresenter



    示例
    1、演示 GridView 和 ListView 的新增特性: GridView 和 ListView 每屏显示的数据量多滚动也流畅
    GridViewAndListView/Employee.cs

    namespace Windows81.Controls.GridViewAndListView
    {
        public class Employee
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public bool IsMale { get; set; }
        }
    }

    GridViewAndListView/TestData.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Windows81.Controls.GridViewAndListView
    {
        public class TestData
        {
            /// <summary>
            /// 返回一个 Employee 数据集合,测试用
            /// </summary>
            public static List<Employee> GetEmployees()
            {
                var employees = new List<Employee>();
    
                for (int i = 0; i < 10000; i++)
                {
                    employees.Add(
                        new Employee
                        {
                            Name = "Name " + i.ToString().PadLeft(4, '0'),
                            Age = new Random(i).Next(20, 60),
                            IsMale = Convert.ToBoolean(i % 2)
                        });
                }
    
                return employees;
            }
        }
    }

    GridViewAndListView/IncrementalData.xaml

    <Page
        x:Name="pageRoot"
        x:Class="Windows81.Controls.GridViewAndListView.IncrementalData"
        DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows81.Controls.GridViewAndListView"
        xmlns:common="using:Windows81.Common"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="Transparent">
    
            <GridView x:Name="gridView" Margin="120 0 0 0"
                      ContainerContentChanging="gridView_ContainerContentChanging">
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Height="100" Width="100" Background="Blue">
                            <Rectangle x:Name="placeholderRectangle" Fill="Red" Height="10" Opacity="0" />
                            <TextBlock x:Name="lblName" Text="{Binding Name}" Foreground="Yellow" />
                            <TextBlock x:Name="lblAge" Text="{Binding Age}" Foreground="Aqua" />
                            <TextBlock x:Name="lblIsMale" Text="{Binding IsMale}" Foreground="Gray" />
                        </StackPanel>
                    </DataTemplate>
                </GridView.ItemTemplate>
            </GridView>
            
        </Grid>
    </Page>

    GridViewAndListView/IncrementalData.xaml.cs

    /*
     * 演示 GridView 和 ListView 的新增特性
     * 
     * 当 GridView 或 ListView 的一屏需要显示的数据量极大时(一屏的 item 多,且每个 item 中的 element 也多),由于每次滚动时需要绘制当前屏的每个 element,这需要占用大量的 ui 资源,所以就会有一些卡顿
     * 为了解决这个问题 win8.1 给出了两种解决方案
     * 1、设置 GridView 或 ListView 的 ShowsScrollingPlaceholders 属性为 true(默认值),每次显示 item 时先会显示占位符(application 级的背景色块),然后再绘制内容
     * 2、通过 GridView 或 ListView 的 ContainerContentChanging 事件,分步绘制 item 中的 element
     */
    
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Navigation;
    using Windows.UI.Xaml.Shapes;
    
    namespace Windows81.Controls.GridViewAndListView
    {
        public sealed partial class IncrementalData : Page
        {
            public IncrementalData()
            {
                this.InitializeComponent();
            }
    
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                gridView.ItemsSource = TestData.GetEmployees();
    
                // 默认值是 true,即为了保证流畅,每次显示 item 时先会显示占位符(application 级的背景色块),然后再绘制内容
                // 本例演示 ContainerContentChanging 事件的使用,所以不会用到这个
                gridView.ShowsScrollingPlaceholders = false;
            }
    
            private void gridView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
            {
                // 交由我处理吧
                args.Handled = true;
    
                // 第 1 阶段绘制
                // args.Phase.ToString(); // 0
    
                StackPanel templateRoot = (StackPanel)args.ItemContainer.ContentTemplateRoot;
                Rectangle placeholderRectangle = (Rectangle)templateRoot.FindName("placeholderRectangle");
                TextBlock lblName = (TextBlock)templateRoot.FindName("lblName");
                TextBlock lblAge = (TextBlock)templateRoot.FindName("lblAge");
                TextBlock lblIsMale = (TextBlock)templateRoot.FindName("lblIsMale");
    
                // 显示自定义占位符(也可以不用这个,而是直接显示 item 的背景)
                placeholderRectangle.Opacity = 1;
    
                // 除了占位符外,所有 item 全部暂时不绘制
                lblName.Opacity = 0;
                lblAge.Opacity = 0;
                lblIsMale.Opacity = 0;
    
                // 开始下一阶段的绘制
                args.RegisterUpdateCallback(ShowName);
            }
    
            private void ShowName(ListViewBase sender, ContainerContentChangingEventArgs args)
            {
                // 第 2 阶段绘制
                // args.Phase.ToString(); // 1
    
                Employee employee = (Employee)args.Item;
                SelectorItem itemContainer = (SelectorItem)args.ItemContainer;
                StackPanel templateRoot = (StackPanel)itemContainer.ContentTemplateRoot;
                TextBlock lblName = (TextBlock)templateRoot.FindName("lblName");
    
                // 绘制第 2 阶段的内容
                lblName.Text = employee.Name;
                lblName.Opacity = 1;
    
                // 开始下一阶段的绘制
                args.RegisterUpdateCallback(ShowAge);
            }
    
            private void ShowAge(ListViewBase sender, ContainerContentChangingEventArgs args)
            {
                // 第 3 阶段绘制
                // args.Phase.ToString(); // 2
    
                Employee employee = (Employee)args.Item;
                SelectorItem itemContainer = (SelectorItem)args.ItemContainer;
                StackPanel templateRoot = (StackPanel)itemContainer.ContentTemplateRoot;
                TextBlock lblAge = (TextBlock)templateRoot.FindName("lblAge");
    
                // 绘制第 3 阶段的内容
                lblAge.Text = employee.Age.ToString();
                lblAge.Opacity = 1;
    
                // 开始下一阶段的绘制
                args.RegisterUpdateCallback(ShowIsMale);
            }
    
            private void ShowIsMale(ListViewBase sender, ContainerContentChangingEventArgs args)
            {
                // 第 4 阶段绘制
                // args.Phase.ToString(); // 3
    
                Employee employee = (Employee)args.Item;
                SelectorItem itemContainer = (SelectorItem)args.ItemContainer;
                StackPanel templateRoot = (StackPanel)itemContainer.ContentTemplateRoot;
                Rectangle placeholderRectangle = (Rectangle)templateRoot.FindName("placeholderRectangle");
                TextBlock lblIsMale = (TextBlock)templateRoot.FindName("lblIsMale");
    
                // 绘制第 4 阶段的内容
                lblIsMale.Text = employee.IsMale.ToString();
                lblIsMale.Opacity = 1;
    
                // 隐藏自定义占位符
                placeholderRectangle.Opacity = 0;
            }
        }
    }


    2、GridViewItemPresenter 和 ListViewItemPresenter - 用于设置控件的各种状态(win8.1 新引入),比 win8 的方式更方便,且更快(win8 的方式是全部加载完后再显示,win8.1 的此方式是需要的时候才加载)
    GridViewAndListView/ItemPresenter.xaml

    <Page
        x:Class="Windows81.Controls.GridViewAndListView.ItemPresenter"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows81.Controls.GridViewAndListView"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Page.Resources>
            <Style x:Key="MyGridViewItemPresenterTemplate" TargetType="GridViewItem">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="GridViewItem">
                            <!--
                                GridViewItemPresenter 和 ListViewItemPresenter - 用于设置控件的各种状态(win8.1 新引入),比 win8 的方式更方便,且更快(win8 的方式是全部加载完后再显示,win8.1 的此方式是需要的时候才加载)
                                    Margin - item 的 margin
                                    SelectionCheckMarkVisualEnabled - 是否显示选中状态的标记
                                    SelectedBorderThickness - 选中状态的边框粗细
                                    SelectedBackground - 选中状态的边框颜色
                                    CheckBrush - 选中状态的图标(本例就是那个小对勾)
                                    ...... - 还有好多好多,看文档吧
                            -->
                            <GridViewItemPresenter Margin="10" SelectionCheckMarkVisualEnabled="True" SelectedBorderThickness="3" SelectedBackground="Red" CheckBrush="{ThemeResource ListViewItemCheckThemeBrush}"/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Page.Resources>
    
        <Grid Background="Transparent">
            <GridView x:Name="gridView" Margin="120 0 0 0" 
                      ItemContainerStyle="{StaticResource MyGridViewItemPresenterTemplate}"
                      SelectionMode="Multiple">
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Height="100" Width="100" Background="Blue">
                            <TextBlock x:Name="lblName" Text="{Binding Name}" Foreground="Yellow" />
                            <TextBlock x:Name="lblAge" Text="{Binding Age}" Foreground="Aqua" />
                            <TextBlock x:Name="lblIsMale" Text="{Binding IsMale}" Foreground="Gray" />
                        </StackPanel>
                    </DataTemplate>
                </GridView.ItemTemplate>
            </GridView>
        </Grid>
    </Page>

    GridViewAndListView/ItemPresenter.xaml.cs

    /*
     * GridViewItemPresenter 和 ListViewItemPresenter - 用于设置控件的各种状态(win8.1 新引入),比 win8 的方式更方便,且更快(win8 的方式是全部加载完后再显示,win8.1 的此方式是需要的时候才加载)
     */
    
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Navigation;
    
    namespace Windows81.Controls.GridViewAndListView
    {
        public sealed partial class ItemPresenter : Page
        {
            public ItemPresenter()
            {
                this.InitializeComponent();
            }
    
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                gridView.ItemsSource = TestData.GetEmployees();
            }
        }
    }


    3、演示自定义 GridViewItemPresenter 和 ListViewItemPresenter 的使用
    GridViewAndListView/MyItemPresenter.cs

    /*
     * 自定义 GridViewItemPresenter 和 ListViewItemPresenter
     * 
     * 本例演示如何自定义一个 ContentPresenter 类,以用于 GridView(参见:ItemPresenterCustom.xaml)
     */
    
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Media.Animation;
    using Windows.UI.Xaml.Shapes;
    
    namespace Windows81.Controls.GridViewAndListView
    {
        class MyItemPresenter : ContentPresenter
        {
            Grid _contentGrid = null; // item 的 grid(数据模板中的 Grid,也就是说要使用本例的这个 ContentPresenter 则数据模板中必须要用 Grid 做容器)
            Rectangle _pointerOverBorder = null; // 鼠标经过
            Rectangle _focusVisual = null; // 选中
    
            PointerDownThemeAnimation _pointerDownAnimation = null;
            Storyboard _pointerDownStoryboard = null;
    
            GridView _parentGridView;
    
            public MyItemPresenter()
                : base()
            {
                base.Margin = new Thickness(10);
            }
    
            protected override void OnApplyTemplate()
            {
                base.OnApplyTemplate();
    
                var obj = VisualTreeHelper.GetParent(this);
                while (!(obj is GridView))
                {
                    obj = VisualTreeHelper.GetParent(obj);
                }
                _parentGridView = (GridView)obj;
    
                _contentGrid = (Grid)VisualTreeHelper.GetChild(this, 0);
            }
    
            protected override bool GoToElementStateCore(string stateName, bool useTransitions)
            {
                base.GoToElementStateCore(stateName, useTransitions);
    
                switch (stateName)
                {
                    // 正常状态
                    case "Normal":
                        HidePointerOverVisuals();
                        HideFocusVisuals();
                        if (useTransitions)
                        {
                            StopPointerDownAnimation();
                        }
                        break;
    
                    // 选中状态
                    case "Focused":
                    case "PointerFocused":
                        ShowFocusVisuals();
                        break;
    
                    // 取消选中状态
                    case "Unfocused":
                        HideFocusVisuals();
                        break;
    
                    // 鼠标经过状态
                    case "PointerOver":
                        ShowPointerOverVisuals();
                        if (useTransitions)
                        {
                            StopPointerDownAnimation();
                        }
                        break;
    
                    // 鼠标点击状态
                    case "Pressed":
                    case "PointerOverPressed":
                        if (useTransitions)
                        {
                            StartPointerDownAnimation();
                        }
                        break;
    
                    default: break;
                }
    
                return true;
            }
    
            private void StartPointerDownAnimation()
            {
                if (_pointerDownStoryboard == null)
                    CreatePointerDownStoryboard();
    
                _pointerDownStoryboard.Begin();
            }
    
            private void StopPointerDownAnimation()
            {
                if (_pointerDownStoryboard != null)
                    _pointerDownStoryboard.Stop();
            }
    
            private void ShowFocusVisuals()
            {    
                if (!FocusElementsAreCreated())
                    CreateFocusElements();
    
                _focusVisual.Opacity = 1;
            }
    
            private void HideFocusVisuals()
            {
                if (FocusElementsAreCreated())
                    _focusVisual.Opacity = 0;
            }
    
            private void ShowPointerOverVisuals()
            { 
                if (!PointerOverElementsAreCreated())
                    CreatePointerOverElements();
    
                _pointerOverBorder.Opacity = 1;
            }
    
            private void HidePointerOverVisuals()
            {
                if (PointerOverElementsAreCreated())
                    _pointerOverBorder.Opacity = 0;
            }
    
            private void CreatePointerDownStoryboard()
            {
                _pointerDownAnimation = new PointerDownThemeAnimation();
                Storyboard.SetTarget(_pointerDownAnimation, _contentGrid);
    
                _pointerDownStoryboard = new Storyboard();
                _pointerDownStoryboard.Children.Add(_pointerDownAnimation);
            }
    
            private void CreatePointerOverElements()
            {
                _pointerOverBorder = new Rectangle();
                _pointerOverBorder.IsHitTestVisible = false;
                _pointerOverBorder.Opacity = 0;
                _pointerOverBorder.Fill = (SolidColorBrush)_parentGridView.Resources["PointerOverBrush"]; // 此资源要预先在 GridView 中定义
    
                _contentGrid.Children.Insert(_contentGrid.Children.Count, _pointerOverBorder);
            }
    
            private void CreateFocusElements()
            {
                _focusVisual = new Rectangle();
                _focusVisual.IsHitTestVisible = false;
                _focusVisual.Height = 10;
                _focusVisual.StrokeThickness = 2;
                _focusVisual.VerticalAlignment = VerticalAlignment.Bottom;
                _focusVisual.Fill = (SolidColorBrush)_parentGridView.Resources["FocusBrush"]; // 此资源要预先在 GridView 中定义
                _focusVisual.Stroke = (SolidColorBrush)_parentGridView.Resources["FocusBrush"]; // 此资源要预先在 GridView 中定义
    
                _contentGrid.Children.Insert(0, _focusVisual);
            }
    
            private bool FocusElementsAreCreated()
            {
                return _focusVisual != null;
            }
    
            private bool PointerOverElementsAreCreated()
            {
                return _pointerOverBorder != null;
            }
        }
    }

    GridViewAndListView/ItemPresenterCustom.xaml

    <Page
        x:Class="Windows81.Controls.GridViewAndListView.ItemPresenterCustom"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows81.Controls.GridViewAndListView"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Page.Resources>
            <Style x:Key="MyGridViewItemPresenterTemplate" TargetType="GridViewItem">
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="GridViewItem">
                            <!--
                                自定义 GridViewItemPresenter 和 ListViewItemPresenter
                                关于 GridViewItemPresenter 和 ListViewItemPresenter 的说明参见:ItemPresenter.xaml
                            
                                MyItemPresenter 参见 MyItemPresenter.cs
                            -->
                            <local:MyItemPresenter/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Page.Resources>
    
        <Grid Background="Transparent">
            <GridView x:Name="gridView" Margin="120 0 0 0" 
                      ItemContainerStyle="{StaticResource MyGridViewItemPresenterTemplate}"
                      SelectionMode="Multiple">
                <GridView.Resources>
                    <!--MyItemPresenter.cs 中需要用到的资源-->
                    <SolidColorBrush x:Name="PointerOverBrush" Color="#50505050"/>
                    <SolidColorBrush x:Name="FocusBrush" Color="#ffff0000"/>
                </GridView.Resources>
                <GridView.ItemTemplate>
                    <DataTemplate>
                        <Grid Height="100" Width="100" Background="Blue">
                            <TextBlock x:Name="lblName" Text="{Binding Name}" Foreground="Yellow" />
                        </Grid>
                    </DataTemplate>
                </GridView.ItemTemplate>
            </GridView>
        </Grid>
    </Page>

    GridViewAndListView/ItemPresenterCustom.xaml.cs

    /*
     * 演示自定义 GridViewItemPresenter 和 ListViewItemPresenter 的使用
     * 
     * 关于 GridViewItemPresenter 和 ListViewItemPresenter 的说明参见:ItemPresenter.xaml
     */
    
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Navigation;
    
    namespace Windows81.Controls.GridViewAndListView
    {
        public sealed partial class ItemPresenterCustom : Page
        {
            public ItemPresenterCustom()
            {
                this.InitializeComponent();
            }
    
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                gridView.ItemsSource = TestData.GetEmployees();
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    爬取虎牙小姐姐热舞 Python
    爬某音乐平台的付费音乐 Python 被标题党搞烦了的可以来看看
    爬取某站的文档 Python
    解决网页复制限制
    英文拼写检查
    记测评文章
    Standard Deviation (SD), Standard Error (SE),Confidence Interval (CI). 画barplot,置信区间
    conditional analysis 把发现的lead SNP作为协变量看LD内是否有其他显著SNP
    知网下载pdf格式
    MAC环境配置
  • 原文地址:https://www.cnblogs.com/webabcd/p/4203632.html
Copyright © 2020-2023  润新知