Spook
Spook

Reputation: 25927

WPF, button inheriting Foreground for its content

The problem: how can I design button, which inherits Foreground from its parent, but allows changing it via style?

More precisely, given following button:

<StackPanel TextBlock.Foreground="Red">
<ToggleButton Width="16" Height="16" FontSize="10" Style="{StaticResource ...}">
    <Grid>
        <Path Width="8" Height="8" Fill="...">
            <Path.Data>
                <PathGeometry Figures="M 1 0 L 1 4 L 0 4 L 0 5 L 3 5 L 3 8 L 4 8 L 4 5 L 7 5 L 7 4 L 6 4 L 6 0 L 1 0 z M 2 1 L 4 1 L 4 4 L 2 4 L 2 1 z " FillRule="NonZero"/>
            </Path.Data>
        </Path>
    </Grid>
</ToggleButton>
</StackPanel>

I need, that:

I tried designing style for button, including the ControlTemplate, but there's a problem with Foreground. Button has its Foreground property set to some DynamicResource via theme, so it doesn't match StackPanel's Foreground.

Obviously I can bind it, but then style and control template triggers stops working, because I've set an immediate value to a dependency property, what overrules all other means of providing value to it.

To give a context to the problem, this is what I want to achieve:

enter image description here

Upvotes: 0

Views: 713

Answers (2)

Spook
Spook

Reputation: 25927

I figured it out by myself - I forgot, that style setters may set bindings as well. The solution is following.

Style:

<Style TargetType="ButtonBase" x:Key="DocumentTabButtonStyle">
    <Style.Setters>
        <Setter Property="TextBlock.Foreground" Value="{Binding Path=(TextBlock.Foreground), RelativeSource={RelativeSource AncestorType=StackPanel}}" />
        <Setter Property="Template">
            ...                
        </Setter>
    </Style.Setters>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="TextBlock.Foreground" Value="{StaticResource DocumentButtonHoverForegroundBrush}"/>
        </Trigger>
    </Style.Triggers>
</Style>

Button:

<Button Style="{StaticResource DocumentTabButtonStyle}">
    <Path Fill="{Binding Path=(TextBlock.Foreground), RelativeSource={RelativeSource AncestorType={x:Type Button}}}">
        <Path.Data>
            <PathGeometry Figures="M 0 1 L 3 4 L 0 7 L 2 7 L 4 5 L 6 7 L 8 7 L 5 4 L 8 1 L 6 1 L 4 3 L 2 1 Z" />
        </Path.Data>
    </Path>
</Button>

Upvotes: 0

mm8
mm8

Reputation: 169200

You could bind to the attached TextBlock.Foreground of the ToggleButton's parent Panel like this:

<Path Width="8" Height="8"
       Fill="{Binding (TextBlock.Foreground), 
           RelativeSource={RelativeSource AncestorType=Panel, AncestorLevel=2}}">
...

If you want the Fill to change on mouse over, you could define a Style with a DataTrigger:

<StackPanel TextBlock.Foreground="Red">
    <ToggleButton Width="16" Height="16" FontSize="10">
        <Grid>
            <Path Width="8" Height="8">
                <Path.Data>
                    <PathGeometry Figures="M 1 0 L 1 4 L 0 4 L 0 5 L 3 5 L 3 8 L 4 8 L 4 5 L 7 5 L 7 4 L 6 4 L 6 0 L 1 0 z M 2 1 L 4 1 L 4 4 L 2 4 L 2 1 z "
                                  FillRule="NonZero"/>
                </Path.Data>
                <Path.Style>
                    <Style TargetType="Path">
                        <Setter Property="Fill" Value="{Binding (TextBlock.Foreground), 
                     RelativeSource={RelativeSource AncestorType=Panel, AncestorLevel=2}}" />
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding IsMouseOver, 
                    RelativeSource={RelativeSource AncestorType=ToggleButton}}" Value="True">
                                <Setter Property="Fill" Value="Blue" />
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </Path.Style>
            </Path>
        </Grid>
    </ToggleButton>
</StackPanel>

Upvotes: 1

Related Questions