UWP开发里,Pivot真是个令人又爱又恨的控件。为了实现某些可滚动Header的效果,有些大佬甚至去掉了原本的Header,使用一个ListView或者ListBox自己画Header,不过这样会让控件变得很复杂。
既然Pivot是一个模板化控件,那么应该有方法直接让Header可以滚动。
先贴效果图:
先自定义Pivot的Style,从generic.xaml找(位置应该在C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\(你的SDK版本)\Generic),或者在xaml设计器里右键,编辑Style也可以。
找到Style中的<VisualStateGroup x:Name="NavigationButtonsVisibility">,到</VisualStateGroup>,包括这两行,全部注释掉,就可以取消左右两侧的按钮。
分析一下,Pivot有两个状态:
当HeaderPanel宽度小于Pivot宽度的时候,也就是Headers不溢出的时候,Header的位置是固定的;
当HeaderPanel宽度大于Pivot宽度的时候,也就是Headers溢出的时候,被选中的Header会被移动到第一位。
观察一下Style可以得知,这个是HeaderStates这个VisualStateGroup控制的,所以和上面一样,注释掉HeaderStates这个VisualStateGroup,这样就取消了动态Header和固定Header的状态转换。
然后往下找,找到<PivotHeaderPanel x:Name="Header" >到</PivotHeaderPanel>,全部注释掉,这是动态的Header,我们只需要静态的。
然后把<PivotHeaderPanel x:Name="StaticHeader">的Visibility改成Visible,这样就默认使用静态的Header,即使Headers溢出也不会自己移动。
最后,在PivotHeaderPanel外面的Grid外面套一层ScrollViewer,代码会变成下面的样子:
运行一下试试看,Header是不是可以使用鼠标滚轮左右滚动了。
至此,本文就已经可以结束了。不过有人可能会问,为什么你的Pivot会有下面的Focus,我的就没有呢?请接着往下看:
从xaml设计器贴出来的Pivot的Style里,并没有Header相关的,Selected、Unselected之类的VisualState,是微软忘了写?其实并不是。
如果你和ItemsControl经常打交道,你会发现ListView、GridView之类的控件都有个ItemContainerStyle属性,控制Items的容器的Style,一般来说Select之类的VisualState都在这里面,可是Pivot并没有提供Header的ItemContainerStyle啊?
其实PivotHeaderItemContainerStyle也是有的,只是微软没有直接提供给我们,需要手动从文件里复制一下,并且用一些非常规的方式使其生效。
首先打开generic.xaml,,在里面全局搜索PivotHeaderItem,可以找到如下段落:
将这一段复制出来,这时你有三个选择:
- 如果你自定义了Pivot的Style,请将这段放在<ControlTemplate TargetType="Pivot"> <Grid x:Name="RootElement" ...><Grid.Resource>(放在这里)</Grid.Resource>。
- 如果没有自定义Style,请将这段放在<Pivot><Pivot.Resource>(放在这里)</Pivot.Resource>
- 单独写在资源字典或者Page.Resource或者Application.Resource里,把x:Key设置为PivotHeaderItemContainerStyle,然后在如上两个位置写<Style TargetType="PivotHeaderItem" BaseOn="{StaticResource PivotHeaderItemContainerStyle}">
注意:对于最终生效的Style(1、2和3中带BaseOn的Style),不要设置x:Key和x:Name!(不设置x:Key和x:Name的Style资源,会应用给他的所有TargetType匹配的子控件。)
这样我们就可以自定义PivotHeaderItemContainerStyle了。
然后找到<VisualStateGroup x:Name="SelectionStates">,在里面的Selected,SelectedPointerOver,SelectedPressed的Storyboard中加入如下的段落:
这样再运行,就可以在Header被选中的时候显示下面的Focus啦。