0

Special thanks to @BionicCode for getting me started here with my user control styling: Styling A Custom Control

I created a simple demo custom control with a button and textblock. Now I'm adding a style for the button.

First, I added a ComponentResourceKey in the code file:

public static ComponentResourceKey ButtonStyleKey = new ComponentResourceKey(typeof(MyCustomControl), "ButtonStyle");

Next, I added the button style to my Generic.xaml file

<Style x:Key="{x:Static local:MyCustomControl.ButtonStyleKey}" 
   TargetType="{x:Type Button}">

<Setter Property="Background" Value="#EEEEEEEE"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="10 5"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="BorderThickness" Value="2" />

<Setter Property="Template">
    <Setter.Value>
        
        <ControlTemplate TargetType="{x:Type Button}">
            
            <Grid>

                <Border x:Name="Border"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"/>

                <ContentPresenter x:Name="content" 
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                  Margin="{TemplateBinding Padding}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                  RecognizesAccessKey="True" />
            </Grid>
            
            <ControlTemplate.Triggers>
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Foreground" Value="Red"/>
                    <Setter Property="Margin" Value="2 1" />
                </Trigger>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="BorderThickness" Value="0"/>
                    <Setter Property="Background" Value="Orange"/>
                    <Setter Property="Foreground" Value="Blue"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Foreground" Value="Gray"/>
                    <Setter Property="Foreground" Value="DarkGray"/>
                </Trigger>
            </ControlTemplate.Triggers>
            
        </ControlTemplate>
        
    </Setter.Value>
</Setter>

Here's the button in the control template

<Button Grid.Row="0" 
    x:Name="button"
    Height="65"
    Width="150"
    Content="A Button"
    Style="{DynamicResource {x:Static local:MyCustomControl.ButtonStyleKey}}"/>

The problem is with the IsPressed trigger. The background color does not change to red.

The MouseOver trigger works fine and sets the button's background to orange, and the IsEnabled trigger sets the colors for disabled as well, so I know the style is working ok otherwise.

13
  • 1
    The answer is correct. Triggers or XAML markup in general is executed in their order of declaration. This is because WPF simply parses the XAML document line by line and converts it to C# code. The order of declaration is also important when you merge resources. Or declare resources (there is no forward declaration, so in order for resource A to be able to reference resource B (e.g., a Brush), resource B must be declared before resource A. Or you overlay elements (using Z-Index). Declaration order in XAML matters. Commented Dec 18, 2023 at 17:51
  • 1
    I recommend looking into the VisualStateManager. It's the recommended way to implement visual states and offer more flexibility compared to triggers. One big advantage is that VisualStates are mutual exclusive. this means your current issues could have been avoided had you used the VisualStateManager. Commented Dec 18, 2023 at 17:52
  • 1
  • 1
    I have also to point out that DynamicResource is very expensive. You should avoid it and only use it if you dynamically replace the referenced resource at runtime. Always prefer StaticResource. There are many reasons to avoid DynamicResource. For example, in your case the resource is in the themes resource dictionary. This means, any exception that are caused by this resource will be thrown at runtime. For this reason, you should also consider declaring the resource in the application resource dictionary instead. Commented Dec 18, 2023 at 18:11
  • Don't I need to make it dynamic if I want the end uer to be able to replace the style later on? Commented Dec 18, 2023 at 22:12

1 Answer 1

3

i think the IsMouseOver will triumph IsPressed since IsMouseOver is defined after IsPressed

try switching them

            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="BorderThickness" Value="0"/>
                <Setter Property="Background" Value="Orange"/>
                <Setter Property="Foreground" Value="Blue"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="True">
                <Setter Property="Foreground" Value="Red"/>
                <Setter Property="Margin" Value="2 1" />
            </Trigger>

if you want to have different behavior when IsMouseOver and IsPressed is true simultaneously you should look into MultiTrigger

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.