需求是第一列锁定,那么怎么让锁定列不跟着滚动条向做移动呢?
其实很简单,让锁定列跟scrollviewer的滚动做反方向移动。
先看一下这个控件的模板,嗯,其实很简单,就是ListView的模板,不同的是ScrollViewer 加上了TopHeader作为Column header。
而这个自定义的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的模板也得重写,重点改变在下面:
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。想要更多功能的童鞋可以看看.
开源有益:
注意: 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)) { ... }