UWP Composition API - 锁定列的FlexGrid

简介: 原文:UWP Composition API - 锁定列的FlexGrid 需求是第一列锁定,那么怎么让锁定列不跟着滚动条向做移动呢? 其实很简单,让锁定列跟scrollviewer的滚动做反方向移动。
原文: UWP Composition API - 锁定列的FlexGrid

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

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

 

目录
相关文章
|
2月前
|
JavaScript 前端开发 API
Vue.js 3中的Composition API:提升你的组件开发体验
Vue.js 3中的Composition API:提升你的组件开发体验
|
3月前
|
缓存 JavaScript 前端开发
深入理解 Vue 3 的 Composition API 与新特性
本文详细探讨了 Vue 3 中的 Composition API,包括 setup 函数的使用、响应式数据管理(ref、reactive、toRefs 和 toRef)、侦听器(watch 和 watchEffect)以及计算属性(computed)。我们还介绍了自定义 Hooks 的创建与使用,分析了 Vue 2 与 Vue 3 在响应式系统上的重要区别,并概述了组件生命周期钩子、Fragments、Teleport 和 Suspense 等新特性。通过这些内容,读者将能更深入地理解 Vue 3 的设计理念及其在构建现代前端应用中的优势。
68 1
深入理解 Vue 3 的 Composition API 与新特性
|
2月前
|
JavaScript 前端开发 API
Vue 3新特性详解:Composition API的威力
【10月更文挑战第25天】Vue 3 引入的 Composition API 是一组用于组织和复用组件逻辑的新 API。相比 Options API,它提供了更灵活的结构,便于逻辑复用和代码组织,特别适合复杂组件。本文将探讨 Composition API 的优势,并通过示例代码展示其基本用法,帮助开发者更好地理解和应用这一强大工具。
45 2
|
3月前
|
JavaScript API
|
3月前
|
API
《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势
《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势
34 0
|
6天前
|
JSON 前端开发 搜索推荐
关于商品详情 API 接口 JSON 格式返回数据解析的示例
本文介绍商品详情API接口返回的JSON数据解析。最外层为`product`对象,包含商品基本信息(如id、name、price)、分类信息(category)、图片(images)、属性(attributes)、用户评价(reviews)、库存(stock)和卖家信息(seller)。每个字段详细描述了商品的不同方面,帮助开发者准确提取和展示数据。具体结构和字段含义需结合实际业务需求和API文档理解。
|
12天前
|
JSON API 数据格式
京东商品SKU价格接口(Jd.item_get)丨京东API接口指南
京东商品SKU价格接口(Jd.item_get)是京东开放平台提供的API,用于获取商品详细信息及价格。开发者需先注册账号、申请权限并获取密钥,随后通过HTTP请求调用API,传入商品ID等参数,返回JSON格式的商品信息,包括价格、原价等。接口支持GET/POST方式,适用于Python等语言的开发环境。
64 11
|
3天前
|
Web App开发 JSON 测试技术
API测试工具集合:让接口测试更简单高效
在当今软件开发领域,接口测试工具如Postman、Apifox、Swagger等成为确保API正确性、性能和可靠性的关键。Postman全球闻名但高级功能需付费,Apifox则集成了API文档、调试、Mock与自动化测试,简化工作流并提高团队协作效率,特别适合国内用户。Swagger自动生成文档,YApi开源但功能逐渐落后,Insomnia界面简洁却缺乏团队协作支持,Paw仅限Mac系统。综合来看,Apifox是国内用户的理想选择,提供中文界面和免费高效的功能。
|
1月前
|
人工智能 自然语言处理 API
Multimodal Live API:谷歌推出新的 AI 接口,支持多模态交互和低延迟实时互动
谷歌推出的Multimodal Live API是一个支持多模态交互、低延迟实时互动的AI接口,能够处理文本、音频和视频输入,提供自然流畅的对话体验,适用于多种应用场景。
87 3
Multimodal Live API:谷歌推出新的 AI 接口,支持多模态交互和低延迟实时互动
|
23天前
|
JSON 安全 API
淘宝商品详情API接口(item get pro接口概述)
淘宝商品详情API接口旨在帮助开发者获取淘宝商品的详细信息,包括商品标题、描述、价格、库存、销量、评价等。这些信息对于电商企业而言具有极高的价值,可用于商品信息展示、市场分析、价格比较等多种应用场景。

热门文章

最新文章