zoukankan      html  css  js  c++  java
  • UWP Composition API

    需求是第一列锁定,那么怎么让锁定列不跟着滚动条向做移动呢?

    其实很简单,让锁定列跟scrollviewer的滚动做反方向移动。

    先看一下这个控件的模板,嗯,其实很简单,就是ListView的模板,不同的是ScrollViewer 加上了TopHeader作为Column header。

     <Border x:Name="RootBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                            <ScrollViewer x:Name="ScrollViewer" Style="{StaticResource FlexGridScrollViewerStyle}" AutomationProperties.AccessibilityView="Raw" BringIntoViewOnFocusChange="{TemplateBinding ScrollViewer.BringIntoViewOnFocusChange}" HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}" HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}" IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}" IsHorizontalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsHorizontalScrollChainingEnabled}" IsVerticalScrollChainingEnabled="{TemplateBinding ScrollViewer.IsVerticalScrollChainingEnabled}" IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}" IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}" TabNavigation="{TemplateBinding TabNavigation}" VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}" VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}" ZoomMode="{TemplateBinding ScrollViewer.ZoomMode}">
                                <ScrollViewer.TopHeader>
                                    <Grid>
                                        <ListView x:Name="ColumnHeader" SelectionMode="None" IsItemClickEnabled="True" Style="{StaticResource NoScrollViewerListViewStyle}" ItemsSource="{TemplateBinding ColumnsHeaderItemsSource}" ItemTemplate="{TemplateBinding ColumnsHeaderItemTemplate}">
                                            <ListView.ItemsPanel>
                                                <ItemsPanelTemplate>
                                                    <StackPanel Orientation="Horizontal"/>
                                                </ItemsPanelTemplate>
                                            </ListView.ItemsPanel>
                                        </ListView>
                                        <ListView x:Name="FrozenColumnsHeader" Visibility="{TemplateBinding FrozenColumnsVisibility}" HorizontalAlignment="Left" VerticalAlignment="Stretch" SelectionMode="None" IsItemClickEnabled="True" Style="{StaticResource NoScrollViewerListViewStyle}" ItemsSource="{TemplateBinding FrozenColumnsHeaderItemsSource}" ItemTemplate="{TemplateBinding FrozenColumnsHeaderItemTemplate}">
                                            <ListView.ItemsPanel>
                                                <ItemsPanelTemplate>
                                                    <StackPanel Orientation="Horizontal"/>
                                                </ItemsPanelTemplate>
                                            </ListView.ItemsPanel>
                                        </ListView>
                                    </Grid>
                                </ScrollViewer.TopHeader>
    
                                <ItemsPresenter HorizontalAlignment="Left"  VerticalAlignment="Top" FooterTransitions="{TemplateBinding FooterTransitions}" FooterTemplate="{TemplateBinding FooterTemplate}" Footer="{TemplateBinding Footer}"  Padding="{TemplateBinding Padding}"/>
                                <!--HeaderTemplate="{TemplateBinding HeaderTemplate}" Header="{TemplateBinding Header}" HeaderTransitions="{TemplateBinding HeaderTransitions}"-->
                            </ScrollViewer>
                        </Border>

    而这个自定义的ListView的ItemContainer需要重写。

            protected override bool IsItemItsOwnContainerOverride(object item)
            {
                return item is FlexGridItem;
                return base.IsItemItsOwnContainerOverride(item);
            }
    
            protected override DependencyObject GetContainerForItemOverride()
            {
                return new FlexGridItem();
                return base.GetContainerForItemOverride();
            }

    这个重写的FlexGridItem 是继承于ListVIewItem,ListViewItem的模板也得重写,重点改变在下面:

                                <Border x:Name="ContentContainer">
                                    <Grid x:Name="InnerDragContent">
                                        <Border x:Name="ContentBorder"
                                            Background="{TemplateBinding Background}"
                                            BorderBrush="{TemplateBinding BorderBrush}"
                                            BorderThickness="{TemplateBinding BorderThickness}"
                                            Margin="0">
                                            <Grid>
                                                <ContentPresenter x:Name="contentPresenter"
                                                              ContentTransitions="{TemplateBinding ContentTransitions}"
                                                              ContentTemplate="{TemplateBinding ContentTemplate}"
                                                              Content="{TemplateBinding Content}"
                                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                                               />
                                                <!-- The 'Xg' text simulates the amount of space one line of text will occupy.
                                                 In the DataPlaceholder state, the Content is not loaded yet so we
                                                 approximate the size of the item using placeholder text. -->
                                                <Rectangle x:Name="pressedHider" Width="15" Opacity="0" Visibility="{TemplateBinding FrozenColumnsVisibility}" Margin="-10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Stretch" Fill="{ThemeResource ApplicationPageBackgroundThemeBrush}"/>
                                                <ContentPresenter x:Name="frozenContent" Visibility="{TemplateBinding FrozenColumnsVisibility}"
                                                              ContentTransitions="{TemplateBinding ContentTransitions}"
                                                              HorizontalAlignment="Left"
                                                              ContentTemplate="{TemplateBinding FrozenColumnsItemTemplate}"
                                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                                              />
    frozenContent就是我们将要锁定的列。
    在FlexGridItem里面我们让frozenContent跟着Scrollviewer 丝滑的水平滑动.
            internal void StartAnimation(ScrollViewer sv)
            {
                _sv = sv;
                if (_frozenContent == null || _sv == null || _pressedHider == null || _frozenContentVisual != null)
                {
                    return;
                }
                _scrollerViewerManipulation = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(sv);
                _compositor = _scrollerViewerManipulation.Compositor;
                _offsetAnimation = _compositor.CreateExpressionAnimation("-min(0,ScrollManipulation.Translation.X)");
                _offsetAnimation.SetReferenceParameter("ScrollManipulation", _scrollerViewerManipulation);
    
                _frozenContentVisual = ElementCompositionPreview.GetElementVisual(_frozenContent);
                _pressedHiderVisual = ElementCompositionPreview.GetElementVisual(_pressedHider);
                _frozenContentVisual.StartAnimation("Offset.X", _offsetAnimation);
                _pressedHiderVisual.StartAnimation("Offset.X", _offsetAnimation);
            }

    看过之前使用UWP Composition API的童鞋肯定对这个代码还是很眼熟。ScrollViewer 向右移动100,锁定的内容也向右移动100,这样看起来锁定的内容就像是不动的一样。

    不过这种由ListView继续的Grid 局限是比较多,不能随自己的想法来操作ScrollViewer。想要更多功能的童鞋可以看看DataGrid.

    开源有益:FlexGrid

    注意: Composition API 只支持10586以及更高的版本,判断条件如下:

    使用条件:

        // Windows build 10240 and later. 
        if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 1))
        {
            ...
        }
    
        // Windows build10586 and later.
        if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 2))
        {
            ...
        }
    
        // Windows build14332 and later.
        if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3))
        {
            ...
        }
    调试了下
    1. Windows build14332 and later: 1,2,3都为true。 
    2. Windows build10586 and later: 1,2为true。
    3. Windows build 10240 and later: 1为true。

    因为10586之前的版本是不支持Composition API的。所以使用的时候记得判断:

        // Windows build10586 and later.
        if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 2))
        {
            ...
        }
    
    
    
  • 相关阅读:
    云计算是什么?它有哪些形式?
    TensorFlow从0到1之浅谈深度学习(5)
    excel如何快速统计出某一分类的最大值?
    Excel怎样根据出生日期,快速计算出其年龄呢?
    Excel只想显示一部分日期,怎样把其余部分隐藏起来?
    Excel数据透视表的日常应用技巧
    人工智能(机器学习)学习之路推荐
    人工智能之常用数据结构与算法(python)
    excel如何快速计算日期对应的生肖?
    excel 如何制作带下拉框的动态折线图表
  • 原文地址:https://www.cnblogs.com/FaDeKongJian/p/5860148.html
Copyright © 2011-2022 走看看