Home > Software design >  Style inherittance between different target types
Style inherittance between different target types

Time:11-27

I don't know if I am just not understanding right. I am trying to make 2 different button styles for my application: BlueOnWhiteButton and WhiteOnBlueButton.

Both these buttons should be identical, but the foreground and backgrounds are reversed. So far, oh so simple.

Here is the catch: I need my buttons to have rounded corners. This simple requirement doesn't seem to be so simple after all. Also there maybe a little border of a different color on both versions.

Using some things I found on google and stack, I came up with this style for the first one, and it looked promising:

<Style  x:Key="WhiteOnBlueButton"
        TargetType="Button">

    <Setter Property="Background" Value="{StaticResource MainBlue}" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="FontWeight" Value="bold" />

    <Style.Resources>
        <Style TargetType="Border">
            <Setter Property="CornerRadius" Value="5" />
            <Setter Property="BorderThickness" Value="2" />
            <Setter Property="BorderBrush" Value="{StaticResource LightBlue}" />
        </Style>
    </Style.Resources>
</Style>

So far so good, my button looks how I want it. But then, when I try to make a second style underneath, I get an error at runtime because of the Style.Resources redefine. I'll save you the code block, figure the same with a different name and reversed colors.

I am trying to keep the use of the style as simple as possible, I have tried versions with templates, but it made the style a lot more complicated, and I even lost the button text...

What I would like to have is something like this:

<Style x:Key="RoundedButtonCornersNoBorder" TargetType="Border">
    <Setter Property="CornerRadius" Value="4"/>
    <Setter Property="BorderThickness" Value="0" />
</Style>
                    
<Style x:Key="RoundedButtonCorners" TargetType="Border">
    <Setter Property="CornerRadius" Value="4"/>
    <Setter Property="BorderBrush" Value="{StaticResource LightBlue}" />
    <Setter Property="BorderThickness" Value="2" />
</Style>

<Style  x:Key="WhiteOnBlueButton"
        TargetType="Button">

    <Setter Property="Background" Value="{StaticResource MainBlue}" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="FontWeight" Value="bold" />
    <!-- Somehow tell the borders should be taken from the style RoundedButtonCornersNoBorder-->
</Style>

<Style  x:Key="BlueOnWhiteButton"
    TargetType="Button">

    <Setter Property="Background" Value="White" />
    <Setter Property="Foreground" Value="{StaticResource MainBlue}" />
    <Setter Property="FontWeight" Value="bold" />
    <!-- Somehow tell the borders should be taken from the style RoundedButtonCorners-->
</Style>

Is there any way to code that without writing 300 lines of incomprehensible code?

The final goal is to apply the style by simply doing:

<Button
    Style="{DynamicResource WhiteOnBlueButton}"
    Content="CLICK ME!" />

CodePudding user response:

You could move the Border Style in the Resources of a common base Style and derive the final Button Styles from the common base Style by means of the BasedOn property.

Do not set the BorderBrush in the Border Style, but either in the base or final Button Styles. The Border in the Button Template will pick it up from the Button via a TemplateBinding.

<Style x:Key="RoundedButtonCorners" TargetType="Button">
    <Style.Resources>
        <Style TargetType="Border">
            <Setter Property="CornerRadius" Value="5" />
            <Setter Property="BorderThickness" Value="2" />
        </Style>
    </Style.Resources>
    <Setter Property="BorderBrush" Value="{StaticResource LightBlue}"/>
    <Setter Property="FontWeight" Value="Bold" />
</Style>

<Style x:Key="WhiteOnBlueButton" TargetType="Button"
       BasedOn="{StaticResource RoundedButtonCorners}">
    <Setter Property="Background" Value="{StaticResource MainBlue}"/>
    <Setter Property="Foreground" Value="White" />
</Style>

<Style x:Key="BlueOnWhiteButton" TargetType="Button"
       BasedOn="{StaticResource RoundedButtonCorners}">
    <Setter Property="Background" Value="White" />
    <Setter Property="Foreground" Value="{StaticResource MainBlue}" />
</Style>

CodePudding user response:

Turns out we have a library that has a button exposing the border directly.

final styles look like this:

<Style x:Key="WhiteOnBlueButton" TargetType="telerik:RadButton">
    <Setter Property="Foreground" Value="White" />
    <Setter Property="Background" Value="{StaticResource MainBlue}" />
    <Setter Property="FontWeight" Value="bold" />
                        
    <Setter Property="CornerRadius" Value="5" />
    <Setter Property="BorderBrush" Value="{StaticResource LightBlue}" />
    <Setter Property="BorderThickness" Value="0" />
</Style>

<Style x:Key="BlueOnWhiteButton" TargetType="telerik:RadButton">
    <Setter Property="Foreground" Value="{StaticResource MainBlue}" />
    <Setter Property="Background" Value="White" />
    <Setter Property="FontWeight" Value="bold" />

    <Setter Property="CornerRadius" Value="5" />
    <Setter Property="BorderBrush" Value="{StaticResource LightBlue}" />
    <Setter Property="BorderThickness" Value="0" />
</Style>

and then building my button:

<telerik:RadButton
    x:Name="xamlFullTextSearchButton"
    Style="{StaticResource BlueOnWhiteButton}"
    Grid.Column="2"
    Grid.Row="0"
    Content="CLICK ME"
    CornerRadius="4"/>

With this, I don't even loose the clicking animation! It's perfect for what I need!

  • Related