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,代碼會變成下面的樣子:
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollMode="Disabled" >
<Grid Background="{ThemeResource PivotHeaderBackground}">
<Grid.RenderTransform>
<CompositeTransform x:Name="HeaderOffsetTranslateTransform" />
</Grid.RenderTransform>
<PivotHeaderPanel x:Name="StaticHeader" Visibility="Visible" >
<PivotHeaderPanel.RenderTransform>
<CompositeTransform x:Name="StaticHeaderTranslateTransform"/>
</PivotHeaderPanel.RenderTransform>
</PivotHeaderPanel>
<!--<PivotHeaderPanel x:Name="Header" >
<PivotHeaderPanel.RenderTransform>
<CompositeTransform x:Name="HeaderTranslateTransform"/>
</PivotHeaderPanel.RenderTransform>
</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中加入如下的段落:
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusPipe" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
</ObjectAnimationUsingKeyFrames>
這樣再運作,就可以在Header被選中的時候顯示下面的Focus啦。