Introduction

If you want to change the background of a button, you will notice that the standard button loses it's background colour when the button is focussed, or the mouse pointer is over or clicking the button.
This is a question that keeps coming up on the MSDN forums.
This sample shows the reasons for this, and how to overcome the problem.
 

Building the Sample

Just download, unblock, unzip, open and run!
 

Description

In this sample there are four buttons, from raw standard unstyled button, to the final solution.
 

1. Unstyled Button

First let's have a look at the standard button, with a red background
XAML
Edit|Remove
<Button Click="Button_Click" Background="Red" Content="Button 1" Margin="10,0,10,10" Width="100" HorizontalAlignment="Left"/>
When you hover, and click this button you will see that the red is lost. There must be some Triggers somewhere that are also changing the Background property under various conditions. Also, when it is focussed, it flashes.
 

2. Default Styled Button

Using Expression Blend, I am able to extract the default style and template for the standard Button.
XAML
Edit|Remove
<Button Focusable="False" Click="Button_Click_1" Background="Red" Content="Button 2" Margin="10,0,10,10" Style="{DynamicResource DefaultStyle}" Width="100" HorizontalAlignment="Left"/>
Often you will find that the thing you need to change is just a tweak to the standard template, style or trigger. However, with the Button, we find that the trigger is not at Template level. What we find instead is the ButtonChrome:
XAML
Edit|Remove
<Setter Property="Template"> 
    <Setter.Value> 
        <ControlTemplate TargetType="{x:Type Button}"> 
            <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true"> 
                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
            </Microsoft_Windows_Themes:ButtonChrome> 
            <ControlTemplate.Triggers> 
                <Trigger Property="IsKeyboardFocused" Value="true"> 
                    <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/> 
                </Trigger> 
                <Trigger Property="ToggleButton.IsChecked" Value="true"> 
                    <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/> 
                </Trigger> 
                <Trigger Property="IsEnabled" Value="false"> 
                    <Setter Property="Foreground" Value="#ADADAD"/> 
                </Trigger> 
            </ControlTemplate.Triggers> 
        </ControlTemplate> 
    </Setter.Value> 
</Setter> 
It is the ButtonChrome that is doing the changes. in fact everything is contained inside the ButtonChrome, similar way that the Bullet of a Checkbox is responsible for it's own visual states.
We must therefore get rid of ButtonChrome. One way to do this is to edit this default template, and replace ButtonChrome with your own design for a button.
One thing I did do with this button is set Focusable=False, which stops it flashing, at least. 

3. "Simple Style" Button

As I have Expression Blend, I am able to search for and use Blend's built in "Simple Styles". When I click on assets and starttyping "simple", I get the whole set of Simple styles (styles for all the standard controls) like SimpleButton.
When I select SimpleButton, the "Simple Styles.xaml" ResourceDictionary is added to my project and the new button uses that style: 
XAML
Edit|Remove
<Button Click="Button_Click_2" Content="Button 3" Margin="10,0,10,10" Style="{DynamicResource SimpleButton}" Background="Red" Width="100" HorizontalAlignment="Left"/>

Now we can see all the triggers associated with the mouse events in the "SimpleButton" style, in "Simple Styles.xaml"

 

XAML
Edit|Remove
<Setter Property="Template"> 
    <Setter.Value> 
        <ControlTemplate TargetType="{x:Type Button}"> 
            <Grid x:Name="Grid"> 
                <Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"/> 
                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/> 
            </Grid> 
            <ControlTemplate.Triggers> 
                <Trigger Property="IsKeyboardFocused" Value="true"> 
                    <Setter Property="BorderBrush" Value="{DynamicResource DefaultedBorderBrush}" TargetName="Border"/> 
                </Trigger> 
                <Trigger Property="IsMouseOver" Value="true"> 
                    <Setter Property="Background" Value="{DynamicResource MouseOverBrush}" TargetName="Border"/> 
                </Trigger> 
                <Trigger Property="IsPressed" Value="true"> 
                    <Setter Property="Background" Value="{DynamicResource PressedBrush}" TargetName="Border"/> 
                    <Setter Property="BorderBrush" Value="{DynamicResource PressedBorderBrush}" TargetName="Border"/> 
                </Trigger> 
                <Trigger Property="IsEnabled" Value="true"/> 
                <Trigger Property="IsEnabled" Value="false"> 
                    <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/> 
                    <Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border"/> 
                    <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/> 
                </Trigger> 
            </ControlTemplate.Triggers> 
        </ControlTemplate> 
    </Setter.Value> 
</Setter>

4. Restyled and working!

So now we can see what is happening, we can fix it. Below I have copied the SimpleButton style and commented out the triggers.
XAML
Edit|Remove
<Button Click="Button_Click_3" Content="Button 4" Margin="10,0,10,10" Style="{DynamicResource CustomButtonStyle}" Background="Red" Width="100" HorizontalAlignment="Left"/>
 
XAML
Edit|Remove
<Setter Property="Template"    <Setter.Value        <ControlTemplate TargetType="{x:Type Button}">                     
            <Grid x:Name="Grid" Cursor="Hand"                <Border CornerRadius="2" x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}"/> 
                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/> 
            </Grid> 
                         <!-- Triggers removed --> 
        </ControlTemplate> 
    </Setter.Value> 
</Setter>
 
Now the Button stays Red.
Now however, you realiase the problem with changing the Button Background. There is no visual feedback to the user that the button is being interacted with.
So ideally you would want to restore the Triggers, but just subtle changes like increasing button size slightly on MouseOver, reducing slightly on MouseDown, to give the effect of depressing the button.
In this example, I just added Cursor=Hand, so you can at least see it is clickable. I also rounded the corners slightly to make it look more like the default button.

 

Source Code Files