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

其实很简单,让锁定列跟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=">
                                        <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=" 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))
    {
        ...
    }
												





											

UWP Composition API - 锁定列的FlexGrid的更多相关文章

  1. UWP Composition API - New FlexGrid 锁定行列

    如果之前看了 UWP Jenkins + NuGet + MSBuild 手把手教你做自动UWP Build 和 App store包 这篇的童鞋,针对VS2017,需要对应更新一下配置,需要的童鞋点 ...

  2. UWP Composition API - GroupListView(二)

    还是先上效果图: 看完了上一篇UWP Composition API - GroupListView(一)的童鞋会问,这不是跟上一篇一样的吗??? 骗点击的?? No,No,其实相对上一个有更简单粗暴 ...

  3. UWP Composition API - GroupListView(一)

    需求: 光看标题大家肯定不知道是什么东西,先上效果图: 这不就是ListView的Group效果吗?? 看上去是的.但是请听完需求.1.Group中的集合需要支持增量加载ISupportIncreme ...

  4. UWP Composition API - RadialMenu

    用Windows 8.1的童鞋应该知道OneNote里面有一个RadialMenu.如下图,下图是WIn10应用Drawboard PDF的RadialMenu,Win8.1的机器不好找了.哈哈,由于 ...

  5. UWP Composition API - PullToRefresh

    背景: 之前用ScrollViewer 来做过 PullToRefresh的控件,在项目一些特殊的条件下总有一些问题,比如ScrollViewer不会及时到达指定位置.于是便有了使用Compositi ...

  6. UWP中使用Composition API实现吸顶(1)

    前几天需要在UWP中实现吸顶,就在网上找了一些文章: 吸顶大法 -- UWP中的工具栏吸顶的实现方式之一 在UWP中页面滑动导航栏置顶 发现前人的实现方式大多是控制ListViewBase的Heade ...

  7. [UWP小白日记-12]使用新的Composition API来实现控件的阴影

    前言 看了好久官方的Windows UI Dev Labs示例好久才有点心得,真是头大.(其实是英语幼儿园水平(⊙﹏⊙)b) 真的网上关于这个API的资料可以说几乎没有. 正文 首先用这东西的添加WI ...

  8. Windows Composition API 指南 - 认识 Composition API

    微软在 Windows 10中 面向通用 Windows 应用 (Universal Windows Apps, UWA) 新引入了一套用于用户界面合成的 API:Composition API.Co ...

  9. 【技巧】datagrid锁定列后重新加载时出现错位问题的解决

    [问题描述]:有时候datagrid设置了锁定列后,在重新加载datagrid数据时,出现锁定列与非锁定列数据错位的问题,如图: [问题分析]:查看css样式我们发现,锁定的列和非锁定的列属于两个不同 ...

随机推荐

  1. Socket请求和Http请求的各自特点、区别及适用场景

    Socket实现服务器与客户端之间的物理连接,并进行数据传输.主要有TCP/UDP两个协议.Socket处于网络协议的传输层.TCP:传输控制协议,面向连接的的协议,稳定可靠.当客户和服务器彼此交换数 ...

  2. 【BZOJ】2321: [BeiJing2011集训]星器(数学+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2321 完全想不到.. 第一眼以为是爆搜,看到数据范围果断放弃:第二眼以为是网络流(因为只有行列操作, ...

  3. H5与Native交互的实现

    PDF文件下载:将后缀png改成PDF.

  4. Lotus 迁移到Exchange POC 之安装Exchange 2010!

    我们登录到Exchange 2010服务器,双击setup 安装Exchange 2010,双击setup.exe完成安装:

  5. hdu 4671 Backup Plan(签到题)

    错成那样,还以为是卡时间卡精度的变态题,结果就那么ac了= = 悔死我了 题意就不概述了,只要处理前两列即可.其中第一列顺序直接扫一遍,第二列要先处理较少的那几种.我是接着第一列用 head[] 继续 ...

  6. BZOJ 1072 [SCOI2007]排列perm

    1072: [SCOI2007]排列perm Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1268  Solved: 782[Submit][Sta ...

  7. CentOS 安装easy_install、pip的方法

    CentOS 安装easy_install的方法: wget -q http://peak.telecommunity.com/dist/ez_setup.py python ez_setup.py ...

  8. GitHub上搭建个人网站

    大致如下步骤: 1.注册Git账号 2.创建SSH keys 3.新建repository --- 4.设置网站 5.clone库到本地 6.提交.上传 7.预览 本教程默认你了解GitHub的基础之 ...

  9. *更新*无需root,一条命令强制全屏模式

    未root的系统,必须通过pc端运行adb命令进行设置,因此请开启开发者选项中的adb调试模式,用usb连接电脑和手机,运行下面的代码强制开启全屏模式,立即生效:全屏沉浸: adb shell set ...

  10. Spring详解(四)------注解配置IOC、DI

    Annotation(注解)是JDK1.5及以后版本引入的.它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查.注解是以‘@注解名’在代码中存在的. 前面讲解 IOC 和 DI 都是通过 ...