Search code examples
xamlwindows-store-appsuwp

XAML, Pivot: how to bind a PivotHeader property inside PivotHeader definition?


I edited the default Pivot Header Item Style to change its foreground property when a user changes the selected pivot item to a color of mine (See VisualState Selected, I didn't pasted everything):

<Style TargetType="PivotHeaderItem">
        <!-- ... -->
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="PivotHeaderItem">
                    <Grid x:Name="Grid" Background="{TemplateBinding Background}">
                        <!-- ... -->
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="SelectionStates">
                                <VisualStateGroup.Transitions>
                                     <!-- ... -->
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="Disabled">
                                    <!-- ... -->
                                </VisualState>
                                <VisualState x:Name="Unselected" />
                                <VisualState x:Name="UnselectedLocked">
                                    <!-- ... -->
                                </VisualState>
                                <VisualState x:Name="Selected">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource MyColor}" />
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Grid" Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                 <!-- ... -->
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <!-- ... -->
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

If my PivotItem.Header is defined as a TextBlock, the foreground changes as expected.

Now I want the same with Ellipse. The problem is that Ellipse doesn't have a foreground property. I thought I maybe have to bind the fill brush to the foreground brush, but I don't know how to do it.

 <Pivot Grid.Row="1">

    <PivotItem x:Name="Test">

        <PivotItem.Header>
            <Grid>

                <Ellipse
                         Fill="{How to bind PivotItemHeader Foreground?}"
                         Width="20" Height="20" />
            </Grid>
        </PivotItem.Header>

    </PivotItem>

    <PivotItem x:Name="Test2">

        <PivotItem.Header>
            <Grid>

                <Ellipse
                         Fill="{How to bind PivotItemHeader Foreground?}"
                         Width="20" Height="20" />
            </Grid>
        </PivotItem.Header>

    </PivotItem>

</Pivot>

I tried with no success:

Fill="{Binding ElementName=Test, Path=HeaderItem.Foreground}"

Solution

  • In your Template, you change the Foreground of ContentPresenter in the Selected VisualState. So I assume that you want to make a Ellipse as header of each item, and change the color of these ellipses when you select each item.

    To do this, you can use your modified template with Pivot.HeaderTemplate and use the RelativeSource property like this:

    <Pivot Grid.Row="1">
        <Pivot.HeaderTemplate>
            <DataTemplate>
                <Grid>
                    <Ellipse Width="20" Height="20" Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}" />
                </Grid>
            </DataTemplate>
        </Pivot.HeaderTemplate>
        <PivotItem>
            <TextBlock Text="11111" />
        </PivotItem>
    
        <PivotItem>
            <TextBlock Text="22222" />
        </PivotItem>
    </Pivot>
    

    Here the DataTemplate is applied to the ContentPresenter in your modified template, so we can use TemplatedParent to bind the Ellipse to its Parent.

    Or here is another method, you can modify your template like this:

    <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Margin="{TemplateBinding Padding}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" FontWeight="{TemplateBinding FontWeight}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
        <ContentPresenter.RenderTransform>
            <TranslateTransform x:Name="ContentPresenterTranslateTransform" />
        </ContentPresenter.RenderTransform>
        <Ellipse Width="20" Height="20" Fill="{Binding ElementName=ContentPresenter, Path=Foreground}" />
    </ContentPresenter>
    

    and meanwhile use Pivot control like this:

    <Pivot Grid.Row="1">
        <PivotItem>
            <TextBlock Text="11111" />
        </PivotItem>
    
        <PivotItem>
            <TextBlock Text="22222" />
        </PivotItem>
    </Pivot>
    

    Just be aware that your "change color" part of the template target the ContentPresenter, not a HeaderItem, you can see this ContentPresenter with the help of LiveVisual Tree.