Search code examples
wpfxamlstylestextblock

Styling both Hyperlink and TextBlock with a single style?


I have two types of text that need to follow similar coloring rules based on an enumeration:

 public enum Modes
 {
   A,
   B,
   C
 }

A Style with DataTrigger markup is used to colorize:

      <Style TargetType="SEE BELOW" x:Key="Coloring">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=.}" Value="A">
                    <Setter Property="Foreground" Value="Red" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Path=.}" Value="B">
                    <Setter Property="Foreground" Value="Green" />
                </DataTrigger>
               <DataTrigger Binding="{Binding Path=.}" Value="C">
                    <Setter Property="Foreground" Value="Blue" />
                </DataTrigger>
            </Style.Triggers>
        </Style>

One use scenario is a System.Windows.Documents.Hyperlink with a nested System.Windows.Controls.TextBlock:

<Hyperlink><TextBlock/></Hyperlink>

and the other is just a simple TextBlock:

<TextBlock Style="{StaticResource Coloring}" Text="yada"/>

I can, of course, style both TextBlock elements:

<TextBlock Style="{StaticResource Coloring}" Text="yada"/>
<Hyperlink><TextBlock Style="{StaticResource Coloring}"/></Hyperlink>

but that fails to style the underline of the Hyperlink case.

If I try to style across both types:

<TextBlock Style="{StaticResource Coloring}" Text="yada"/>
<Hyperlink Style="{StaticResource Coloring}"><TextBlock/></Hyperlink>

Then the styling fails, as there is (apparently) no common ancestor type for use in the TargetType attribute of the Style.

Since this is suppposed to ultimately be a configurable thing, the goal is to have an XAML document that defines a mode to color mapping for these text blocks. Thus I am reluctant to have two redundant styles (one for Hyperlink and one for TextBlock) that define the same mapping.

So...the question: How can I consistently style both cases without redundant Style XAML blocks?


Solution

  • You can force Hyperlinks to have the same foreground colour as their parent TextBlocks by binding them within the style itself, like this:

    <Style TargetType="TextBlock" x:Key="Coloring">
            <Style.Resources>
                <Style TargetType="Hyperlink">
                    <Setter Property="Foreground" Value="{Binding Foreground,RelativeSource={RelativeSource FindAncestor,AncestorType=TextBlock}}"/>
                </Style>
            </Style.Resources>
                <Setter Property="Foreground" Value="Orange"/>
            <Style.Triggers>
            <DataTrigger Binding="{Binding Path=.}" Value="A">
                <Setter Property="Foreground" Value="Red" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=.}" Value="B">
                <Setter Property="Foreground" Value="Green" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=.}" Value="C">
                <Setter Property="Foreground" Value="Blue" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
    

    In this example I've added a setter to make the default foreground Orange, just for testing purposes.