97

My problem is that in WPF, whenever I try and change the colour of a button's background using triggers or animations, the default mouseover effect (of being grey with that orange glow) seems to take priority.

After extensive searches I'm clueless as to how to remove this effect.

9 Answers 9

121

This is similar to the solution referred by Mark Heath but with not as much code to just create a very basic button, without the built-in mouse over animation effect. It preserves a simple mouse over effect of showing the button border in black.

The style can be inserted into the Window.Resources or UserControl.Resources section for example (as shown).

<UserControl.Resources>
    <!-- This style is used for buttons, to remove the WPF default 'animated' mouse over effect -->
    <Style x:Key="MyButtonStyle" TargetType="Button">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Margin" Value="5"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="border" 
                        BorderThickness="1"
                        Padding="4,2" 
                        BorderBrush="DarkGray" 
                        CornerRadius="3" 
                        Background="{TemplateBinding Background}">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="border" Property="BorderBrush" Value="Black" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

<!-- usage in xaml -->
<Button Style="{StaticResource MyButtonStyle}">Hello!</Button>
Sign up to request clarification or add additional context in comments.

2 Comments

I like that solution a lot. However, the mouse over triggers activates only when the mouse is over the text on the button. I added a textblock with a specified width inside the button to fix that problem.
You sir are a saint.
39

Just to add a very simple solution, that was good enough for me, and I think addresses the OP's issue. I used the solution in this answer except with a regular Background value instead of an image.

<Style x:Key="SomeButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="{TemplateBinding Background}">
                    <ContentPresenter />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

No re-templating beyond forcing the Background to always be the Transparent background from the templated button - mouseover no longer affects the background once this is done. Obviously replace Transparent with any preferred value.

Comments

18

You need to create your own custom button template to have full control over the appearance in all states. Here's a tutorial.

6 Comments

Thanks, that was perfect. It was more complicated to do than I thought it would be, but it all works well now.
For some reason there's 100 answers about creating custom templates for WPF controls, and they are all unnecessarily wrong. There's no reason to struggle to write 50 lines of template code for a button in order to change 1 thing. All you have to do is in the xaml designer right click the control and create a copy of the template code. VS will create a style from that exact button and you can tweak it from there. Takes literally 2 seconds.
@TheMuffinMan Fantastic, but do you find it even slightly strange that it takes 50 lines of template code to stop a button from changing the background color on mouse hover? What a stupidly over complicated framework WPF is.
@Ash Or one could argue it's guiding the user in the direction they should be going. If you have a button that requires a new hover state, that's likely a new TYPE of button; perhaps a navigation button, a tray button, etc. If so, you shouldn't be modifying one-off properties for it, it should have its own control or style group. And that's kind of what this makes you do.
@TheMuffinMan: you truly are the man! 10 years of working with WPF and just found out about the "Edit Template" option!
|
14

The Muffin Man had a very simple answer which worked for me.

To add a little more specific direction, at least for VS 2013:

  • Right-click the control
  • Select Edit Template => Edit a copy...
  • I selected 'Application' for where to save the style
    • From here you can directly edit App.xaml and see the intuitively named properties. For my purposes, I just set RenderMouseOver="False"
  • Then, in the MainWindow.xaml or wherever your GUI is, you can paste the new style at the end of the Button tag, e.g. ... Style="{DynamicResource MouseOverNonDefault}"/>

2 Comments

Who is the Muffin Man?
LOL. He made the second reply to the question-owner-accepted answer. Wasn't sure if you were asking seriously or joking. Hard to tell with a name like Muffin Man.
11

This Link helped me alot http://www.codescratcher.com/wpf/remove-default-mouse-over-effect-on-wpf-buttons/

Define a style in UserControl.Resources or Window.Resources

 <Window.Resources>
        <Style x:Key="MyButton" TargetType="Button">
            <Setter Property="OverridesDefaultStyle" Value="True" />
            <Setter Property="Cursor" Value="Hand" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border Name="border" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Opacity" Value="0.8" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

Then add the style to your button this way Style="{StaticResource MyButton}"

<Button Name="btnSecond" Width="350" Height="120" Margin="15" Style="{StaticResource MyButton}">
    <Button.Background>
        <ImageBrush ImageSource="/Remove_Default_Button_Effect;component/Images/WithStyle.jpg"></ImageBrush>
    </Button.Background>
</Button>

Comments

4

If someone doesn't want to override default Control Template then here is the solution.

You can create DataTemplate for button which can have TextBlock and then you can write Property trigger on IsMouseOver property to disable mouse over effect. Height of TextBlock and Button should be same.

<Button Background="Black" Margin="0" Padding="0" BorderThickness="0" Cursor="Hand" Height="20">
    <Button.ContentTemplate>
        <DataTemplate>
            <TextBlock Text="GO" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" TextDecorations="Underline" Margin="0" Padding="0" Height="20">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Style.Triggers>
                            <Trigger Property ="IsMouseOver" Value="True">
                                <Setter Property= "Background" Value="Black"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
        </DataTemplate>
    </Button.ContentTemplate>
</Button>

Comments

1

An extension on dodgy_coder's answer which adds support for..

  • Maintaining WPF button style
  • Adds support for IsSelected and hover, i.e. a toggled button

        <Style x:Key="Button.Hoverless" TargetType="{x:Type ButtonBase}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ButtonBase}">
                        <Border Name="border"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Padding="{TemplateBinding Padding}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                Background="{TemplateBinding Background}">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                        </Border>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="True" />
                                    <Condition Property="Selector.IsSelected" Value="False" />
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" Value="#FFBEE6FD" />
                            </MultiTrigger>
    
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="True" />
                                    <Condition Property="Selector.IsSelected" Value="True" />
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" Value="#BB90EE90" />
                            </MultiTrigger>
    
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsMouseOver" Value="False" />
                                    <Condition Property="Selector.IsSelected" Value="True" />
                                </MultiTrigger.Conditions>
                                <Setter Property="Background" Value="LightGreen" />
                            </MultiTrigger>
    
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="border" Property="Opacity" Value="0.95" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

examples..

<Button Content="Wipe On" Selector.IsSelected="True" /> <Button Content="Wipe Off" Selector.IsSelected="False" />

Comments

1

Using a template trigger:

<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="White"></Setter>
    ...
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Background="{TemplateBinding Background}">
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="White"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Comments

1

I have seen this question asked a bunch of times and the answers are always some edit to the XAML code. Here is an answer for code behind.

You will need to edit the ControlTemplate for the button, update this through Style. Here is how I did this in a recent project:

// Create the empty Style
var buttonStyle = new Style(typeof(Button));

// Create ControlTemplate without triggers
var template = new ControlTemplate(typeof(Button));
var border = new FrameworkElementFactory(typeof(Border));

// Minimum binding for the button to work
border.SetValue(Border.BackgroundProperty, new TemplateBindingExtension(Button.BackgroundProperty));

// Create the content presenter for button text
var content = new FrameworkElementFactory(typeof(ContentPresenter));
content.SetValue(ContentPresenter.HorizontalAlignmentProperty, HorizontalAlignment.Center);
content.SetValue(ContentPresenter.VerticalAlignmentProperty, VerticalAlignment.Center);
border.AppendChild(content);

template.VisualTree = border;
buttonStyle.Setters.Add(new Setter(Button.TemplateProperty, template));

Now you just need to set the style at button creation:

var newButton = new Button
{
    Content = "Text description",
    Style = buttonStyle
};

Hopefully this helps someone else.

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.