views:

310

answers:

2

I'm a rank beginner with WPF and I don't even know where to look to find the answer to this question. This XAML seems very straightforward to me:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
  <Grid>
    <Button>
      <Button.Style>
        <Style TargetType="{x:Type Button}">
        <Style.Triggers>
          <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Background" Value="Green"/>
          </Trigger>      
        </Style.Triggers>
        </Style>
      </Button.Style>
      <Button.Content>Test</Button.Content>
    </Button>
  </Grid>
</Page>

When I mouse over the button, IsMouseOver changes to True and the trigger makes background turns green. For an instant. Then it turns blue.

Even better: if I attach the same setter to the IsFocused property, once I focus on the button the background color throbs between green and blue.

There's something, somewhere in the Button (I'm guessing it's in whatever default theme is being used under Vista) that is making it behave this way. I suspect that there's another property that the trigger needs to set. But what?

+4  A: 

You need to change the Button's Template rather than its Style. Built into the template is something called ButtonChrome, and that is what is causing the irritating blue focus effect. Here is a very simple re-templating of the Button control, taken from the provided Simple Styles:

<Style TargetType="{x:Type Button}">
   <Setter Property="SnapsToDevicePixels" Value="true"/>
   <Setter Property="OverridesDefaultStyle" Value="true"/>
   <Setter Property="MinHeight" Value="23"/>
   <Setter Property="MinWidth" Value="75"/>
   <Setter Property="Template">
     <Setter.Value>
       <ControlTemplate TargetType="{x:Type Button}">
         <Border 
           x:Name="Border"  
           CornerRadius="2" 
           BorderThickness="1"
           Background="#C0C0C0"
           BorderBrush="#404040">
           <ContentPresenter 
             Margin="2"
             HorizontalAlignment="Center"
             VerticalAlignment="Center"
             RecognizesAccessKey="True"/>
         </Border>
         <ControlTemplate.Triggers>
           <Trigger Property="IsKeyboardFocused" Value="true">
             <Setter TargetName="Border" Property="BorderBrush" Value="#202020" />
           </Trigger>
           <Trigger Property="IsDefaulted" Value="true">
             <Setter TargetName="Border" Property="BorderBrush" Value="#202020" />
           </Trigger>
           <Trigger Property="IsMouseOver" Value="true">
             <Setter TargetName="Border" Property="Background" Value="#808080" />
           </Trigger>
           <Trigger Property="IsPressed" Value="true">
             <Setter TargetName="Border" Property="Background" Value="#E0E0E0" />
             <Setter TargetName="Border" Property="BorderBrush" Value="#606060" />
           </Trigger>
           <Trigger Property="IsEnabled" Value="false">
             <Setter TargetName="Border" Property="Background" Value="#EEEEEE" />
             <Setter TargetName="Border" Property="BorderBrush" Value="#AAAAAA" />
             <Setter Property="Foreground" Value="#888888"/>
           </Trigger>
         </ControlTemplate.Triggers>
       </ControlTemplate>
     </Setter.Value>
   </Setter>
 </Style>

You can see that by re-templating the control, you can change its visual tree. The visual tree in this template is nothing more than a Border that contains a ContentPresenter (so you can see the content of the button). I have effectively removed the ButtonChrome from the visual tree this way.

Charlie
Thanks! When you say "the provided Simple Styles," what are you referring to?
Robert Rossney
Check out this article:http://blog.falafel.com/2008/07/17/UsingTheSimpleStylesProjectInVisualStudioToCustomizeWPFControls.aspx
Charlie
+1  A: 

Charlie's answer is good. I simply want to supplement with an explanation of what was going on, and a comment didn't seem the place.

The reason why it was green for an instant and then was blue is because the default theme's ControlTemplate for Button already had an IsMouseOver Trigger to change the background.

Then you added another in your Style. This doesn't replace the existing one because you could have multiple Triggers on the same property and value that have very different Setters and do completely different things.

So it was trying to do both, and did the green one first.

Joel B Fant
That's what I thought was going on. Is there any way to simply remove a trigger if you don't want it, or is re-templating the control the only way?
Robert Rossney
Re-templating is the only way, as far as I know.
Joel B Fant