UWP Composition API - 锁定列的FlexGrid

2021-02-09 18:25

阅读:509

原文:UWP Composition API - 锁定列的FlexGrid

技术分享图片

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

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

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

 "RootBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                        "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}">
                            "ColumnHeader" SelectionMode="None" IsItemClickEnabled="True" Style="{StaticResource NoScrollViewerListViewStyle}" ItemsSource="{TemplateBinding ColumnsHeaderItemsSource}" ItemTemplate="{TemplateBinding ColumnsHeaderItemTemplate}">
                                        "Horizontal"/>
                                            "FrozenColumnsHeader" Visibility="{TemplateBinding FrozenColumnsVisibility}" HorizontalAlignment="Left" VerticalAlignment="Stretch" SelectionMode="None" IsItemClickEnabled="True" Style="{StaticResource NoScrollViewerListViewStyle}" ItemsSource="{TemplateBinding FrozenColumnsHeaderItemsSource}" ItemTemplate="{TemplateBinding FrozenColumnsHeaderItemTemplate}">
                                        "Horizontal"/>
                                            "Left"  VerticalAlignment="Top" FooterTransitions="{TemplateBinding FooterTransitions}" FooterTemplate="{TemplateBinding FooterTemplate}" Footer="{TemplateBinding Footer}"  Padding="{TemplateBinding Padding}"/>
                            
                        

而这个自定义的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的模板也得重写,重点改变在下面:

                            "ContentContainer">
                                "InnerDragContent">
                                    "ContentBorder"
                                        Background="{TemplateBinding Background}"
                                        BorderBrush="{TemplateBinding BorderBrush}"
                                        BorderThickness="{TemplateBinding BorderThickness}"
                                        Margin="0">
                                        "contentPresenter"
                                                          ContentTransitions="{TemplateBinding ContentTransitions}"
                                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                                          Content="{TemplateBinding Content}"
                                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                                           />
                                            
                                            "pressedHider" Width="15" Opacity="0" Visibility="{TemplateBinding FrozenColumnsVisibility}" Margin="-10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Stretch" Fill="{ThemeResource ApplicationPageBackgroundThemeBrush}"/>
                                            "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))
    {
        ...
    }

 


评论


亲,登录后才可以留言!