UWP Composition API - 锁定列的FlexGrid
2021-02-09 18:25
需求是第一列锁定,那么怎么让锁定列不跟着滚动条向做移动呢?
其实很简单,让锁定列跟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))
{
...
}
文章标题:UWP Composition API - 锁定列的FlexGrid
文章链接:http://soscw.com/index.php/essay/53199.html