InvalidOperationException in VS2010 - wpf

I'm using Expression Blend 4 + Visual Studio 2010 Pro to create a WPF application.
I have created an control Style (or should I say Template?) based on a CheckBox using only Blend 4, which works perfectly. However when I go to VS2010 I get the following "error":
'[Unknown]' property does not point to
a DependencyObject in path
'(0).(1)[0].(2)'.
Even though when I run the application it works perfectly fine. Now, I don't need to fix this error, but I would like to get rid of it anyway.
Here is the Style's XAML code:
<Style x:Key="IRSensorCheckBoxStyle" TargetType="{x:Type CheckBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<Grid Cursor="Hand">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.StrokeThickness)" Storyboard.TargetName="ellipse">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.StrokeThickness)" Storyboard.TargetName="ellipse">
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="2"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.StrokeThickness)" Storyboard.TargetName="ellipse">
<EasingDoubleKeyFrame KeyTime="0" Value="2"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="ellipse">
<EasingColorKeyFrame KeyTime="0:0:0.3" Value="Red"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="ellipse">
<EasingColorKeyFrame KeyTime="0:0:0.2" Value="#00FF0000"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse x:Name="ellipse" Stroke="Yellow" StrokeThickness="0">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="Red"/>
<GradientStop Offset="1" Color="#00FF0000"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see the error references to both Storyboards in the Checked and Unchecked states. However I don't agree with the error in that the property is not pointing to a DependencyObject (whatever that is...), because the Target is "ellipse" which is there; and the Target Property is pointing to a Shape's Fill, which is right there (Ellipse's Fill); to GradientStops[0] of a GreadientBrush, which there are 2 GradientStops in a RadialGradientBrush; and finally to the GradientStop's Color property, which is also there.
Does anyone has a suggestion?
Thanks in advance.

Someone helped me with a solution (I don't know if you would call it a direct solution or a work-around):
If you give a name to the GradientStop you can reference its Color property directly:
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop x:Name="Offset0" Color="Red"/>
<GradientStop x:Name="Offset1" Offset="1" Color="#00FF0000"/>
</RadialGradientBrush>
</Ellipse.Fill>
[...]
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="Color" Storyboard.TargetName="Offset0">
<EasingColorKeyFrame KeyTime="0:0:0.3" Value="Red"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="Color" Storyboard.TargetName="Offset0">
<EasingColorKeyFrame KeyTime="0:0:0.2" Value="#00FF0000"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
I guess that this approach shouldn't be necessary, but it certainly looks elegant.

Related

Intermittent exception in storyboard in UWP/Winrt applcation

I am receiving the following exception intermittingly when triggering a storyboard on a user control through a View State.
WinRT information: Cannot resolve TargetProperty (Background).(SolidColorBrush.Color) on specified object
My storyboard is below -
<StackPanel Orientation="Horizontal">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Connecting">
<Storyboard RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd1" Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)">
<DiscreteColorKeyFrame Value="#F7F7F7" KeyTime="0:0:0" />
<DiscreteColorKeyFrame Value="#6CBF25" KeyTime="0:0:1" />
<DiscreteColorKeyFrame Value="#F7F7F7" KeyTime="0:0:5" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Bd1" Storyboard.TargetProperty="(BorderBrush).(SolidColorBrush.Color)">
<DiscreteColorKeyFrame Value="#919191" KeyTime="0:0:0" />
<DiscreteColorKeyFrame Value="#01851F" KeyTime="0:0:1" />
<DiscreteColorKeyFrame Value="#919191" KeyTime="0:0:5" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Bd1" Height="5" />
</StackPanel>
And how I trigger it
VisualStateManager.GoToState(this, "Connecting", false);
This visual state is generally triggered immediately on UserControl load.
Its failing because there isn't a SolidColorBrush defined on Bd1.
Background is of type Brush so you could initilaise with a SolidColorBrush like so and your animation should work. I added BorderBrush as well as you're animating that and a Width so you can see it on the screen
<Border x:Name="Bd1" Width="200" Height="5" Background="Red" BorderBrush="Red" />
Your border has no default color. Therefore you canĀ“t access it from Storyboard.
This will work:
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="BorderAnimationGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Connecting">
<Storyboard RepeatBehavior="Forever">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" Storyboard.TargetName="Bd1">
<EasingColorKeyFrame KeyTime="0" Value="#FFF7F7F7"/>
<EasingColorKeyFrame KeyTime="0:0:1" Value="#FF6CBF25"/>
<EasingColorKeyFrame KeyTime="0:0:5" Value="#FFF7F7F7"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="Bd1">
<EasingColorKeyFrame KeyTime="0" Value="#FF919191"/>
<EasingColorKeyFrame KeyTime="0:0:1" Value="#FF01851F"/>
<EasingColorKeyFrame KeyTime="0:0:5" Value="#FF919191"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Bd1" BorderBrush="#FF919191" BorderThickness="1" Height="5" Background="White">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior>
<Core:GoToStateAction StateName="Connecting"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Border>
</StackPanel>

TextBox , different ControlTemplate + IsEnabled

I have added a style to a textbox, where in I modify the ControlTemplate of the textBox.
I end up having a different control template for the textbox.
But I have a problem.
When I set the IsEnabled property to false, the normal textbox, is just greyed out.
But the one with different control template, still remains white.
Is there something specific I need to add as a part of control template, in order to obtain the default behavior?
thanks
Sandeep
Update -> Added the control template.
<ControlTemplate TargetType="{x:Type commonControls:DerivedTextBox}">
<Border Name="Border"
CornerRadius="2"
Padding="2"
BorderThickness="1">
<Border.Background>
<SolidColorBrush Color="{DynamicResource ControlLightColor}" />
</Border.Background>
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{DynamicResource ControlLightColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ReadOnly">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource DisabledControlDarkColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollViewer Margin="0"
x:Name="PART_ContentHost" />
</Border>
</ControlTemplate>
You have replaced the default XAML that makes the TextBox 'grayed out' when IsEnabled is set to False. If you want to replace this functionaluity, you will need to copy that part of the original ControlTemplate, which you can find at the TextBox Styles and Templates page on MSDN.
In the default ControlTemplate, you will see a VisualState with the name Disabled... that is what you need, but you may as well copy most of the VisualStates from there.
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="Border"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0"
Value="{StaticResource DisabledControlLightColor}" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>

VisualStateManager -- showing mouseover state when control is focused

I am creating a WPF button using Windows 8 styling (formerly metro).
I would like the focused state of the button to show with a solid background. When the mouse is over the control, I would like th background to darken slightly to create the visual cue that the button can be clicked.
Unfortunately, the XAML I've written below does not work. The focused state shows correctly, but when the mouse is over the control, the background does not darken as I would like it to.
<Color x:Key="DoxCycleGreen">
#FF8DC63F
</Color>
<!-- Soft Interface : DoxCycle Green -->
<Color x:Key="DoxCycleGreenSoft">
#FFC0DC8F
</Color>
<Style x:Key="MetroButton" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Focused">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreenSoft}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="Transparent" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderColor" Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="Transparent" >
<Border BorderThickness="1,1,1,1" Padding="2">
<Border.BorderBrush>
<SolidColorBrush x:Name="BorderColor" Color="{StaticResource DoxCycleGreen}"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush x:Name="BackgroundColor" Color="White"/>
</Border.Background>
<ContentPresenter
x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Content">
<TextBlock.Foreground>
<SolidColorBrush x:Name="FontColor" Color="{StaticResource DoxCycleGreen}"/>
</TextBlock.Foreground>
</ContentPresenter>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I've now tested your code. You've got a couple of issues at play here. But the main issue is that a WPF control can only be in one Visual State of a particular State Group at a time. And in cases like you've got here, where the control can be both focused and moused-over, WPF has to make choice of which State to apply (it cannot apply both States since they are in the same State Group). So in this case it is just keeping it in the Focused state and not sending it to the MouseOver state.
A control can be in multiple states if each of those states are in different state groups. From this documentation:
Each VisualStateGroup contains a collection of VisualState objects that are mutually exclusive. That is, the control is always in exactly one state of in each VisualStateGroup.
So our first step to correcting this code is to include the proper state groups that will allow the button to be able to show its Focused state and then show its MouseOver state (other possibilities can be corrected by this change but that's the one you noticed in particular that you didn't get with your previous approach).
To do this, we need to be careful to name our state groups and (especially) our state names correctly. This is because the code internal to the Button class likely makes a call like VisualStateManager.GoToState(this, "VerySpecificStateName", true); (I have not inspected the actual source code of the Button class to verify this, but having written custom controls where I've needed to initiate the state changes, I know it must be something like that). In order to get a list of the state group and state names that we'll need, we could either use Expression Blend to "edit a copy" of the control template (which will populate the needed states for us), or find them here. That documentation shows us that we need a state group called "FocusStates" and two states in that group called "Focused" and "Unfocused" (along with other state groups and states). As an aside, to illustrate how the Button class is initiating its state changes by these specific named states, if you change your original code by replacing the "Focus" state name with "MisspelledFocus", you'll see that your button never enters that state.
Implementing this first change, we could end up with something like:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color"
To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="Transparent" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<!-- Focus States -->
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreenSoft}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
This somewhat solves the problem. However, if you're looking at this in Expression Blend, you'll notice a warning in the state group headings:
We are getting this warning because we are changing the value of an identical property/object pair in more than one state group - in this case the "Color" property of the object named "BackgroundColor". Why could this be an issue? Because of what I said earlier - the fact that a control can be in multiple states at once if those states are in different state groups. So if the user has given the button focus and the user has also moused-over the button, it could be ambiguous to WPF as to which animation to apply, since both states say to animate the same exact property but in different ways.
Also, this first change does not completely get us what we want. If you try giving the button focus, then hover over it, it correctly goes from "Normal", to "Focused", to "MouseOver". But if you now discontinue hovering, you'll see that the button does not return to its "Focused" state.
There are several approaches you could use to remedy this problem and achieve something similar to what you wanted, but just as an example, we could do something like this. (This may not be the cleanest implementation for this, but it fixes the common object/property issue.):
<Color x:Key="DoxCycleGreen">
#FF8DC63F
</Color>
<SolidColorBrush x:Key="DoxCycleGreenBrush" Color="{StaticResource DoxCycleGreen}" />
<!-- Soft Interface : DoxCycle Green -->
<Color x:Key="DoxCycleGreenSoft">
#FFC0DC8F
</Color>
<SolidColorBrush x:Key="DoxCycleGreenSoftBrush" Color="{StaticResource DoxCycleGreenSoft}" />
<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="White" Duration="0:0:0.150" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="MouseOverBorder">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="Transparent" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<!-- Focus States -->
<VisualStateGroup x:Name="FocusStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.15"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="FocusBorder">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="ContentSiteWhiteForeground">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="Transparent" >
<Border x:Name="BaseBorder" BorderThickness="1,1,1,1">
<Border.BorderBrush>
<SolidColorBrush x:Name="BorderColor" Color="{StaticResource DoxCycleGreen}"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush x:Name="BackgroundColor" Color="White"/>
</Border.Background>
</Border>
<Border x:Name="FocusBorder"
BorderThickness="1,1,1,1"
Background="{DynamicResource DoxCycleGreenSoftBrush}"
Opacity="0" />
<Border x:Name="MouseOverBorder"
BorderThickness="1,1,1,1"
Background="{DynamicResource DoxCycleGreenBrush}"
Opacity="0" />
<ContentPresenter
x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Content" Margin="2">
<TextBlock.Foreground>
<SolidColorBrush x:Name="FontColor" Color="{StaticResource DoxCycleGreen}"/>
</TextBlock.Foreground>
</ContentPresenter>
<ContentPresenter
x:Name="ContentSiteWhiteForeground"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Content" Margin="2" Opacity="0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" />
</TextBlock.Foreground>
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now you'll see that we have removed the ambiguity for WPF. And we see that it now handles the case of state changes from "Normal" to "Focus" to "MouseOver" and back to "Focus" correctly.
This is a small edit to Jason's answer. It turns out that his approach which uses two ContentPresenters breaks the operation of the short cut keys. I've made a small adjustment... the short cut keys now work, but the transition animation isn't quite as nice...
<Style x:Key="MetroButton" 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="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="White" Duration="0:0:0.150" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="MouseOverBorder">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="Transparent" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<!-- Focus States -->
<VisualStateGroup x:Name="FocusStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.15"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="FocusBorder">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="Transparent" >
<Border x:Name="BaseBorder" BorderThickness="1,1,1,1">
<Border.BorderBrush>
<SolidColorBrush x:Name="BorderColor" Color="{StaticResource DoxCycleGreen}"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush x:Name="BackgroundColor" Color="White"/>
</Border.Background>
</Border>
<Border x:Name="FocusBorder"
BorderThickness="1"
Background="{DynamicResource DoxCycleGreenSoftBrush}"
Opacity="0" />
<Border x:Name="MouseOverBorder"
BorderThickness="1"
Background="{DynamicResource DoxCycleGreenBrush}"
Opacity="0" />
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
RecognizesAccessKey="True"
ContentSource="Content" Margin="8,4">
<TextBlock.Foreground>
<SolidColorBrush x:Name="FontColor" Color="{StaticResource DoxCycleGreen}"/>
</TextBlock.Foreground>
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Silverlight ToggleButton with images

I am trying to create a Silverlight Toggle button style that would flip between a plus and a minus sign. Unfortunately it is always showing a minus sign. Can anyone tell me what's the problem with this style:
<Style x:Key="PlusMinusToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Unchecked">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="UncheckedVisual" Storyboard.TargetProperty="Opacity" To="0" Duration="1" />
<DoubleAnimation Storyboard.TargetName="CheckedVisual" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="UncheckedVisual" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
<DoubleAnimation Storyboard.TargetName="CheckedVisual" Storyboard.TargetProperty="Opacity" To="0" Duration="1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Image x:Name="UncheckedVisual" Source="plus.png" Stretch="None" />
<Image x:Name="CheckedVisual" Source="minus.png" Stretch="None" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You need to expand on the DoubleAnimation, put in KeyFrame Animation in it. Also set the base opacity to 0 and then fade in the respective one you need. For example:
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="CheckedVisual" Storyboard.TargetProperty="Opacity">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
Everytime a state is changed, it goes back to the base state then to the state that was called. Because a togglebutton is always in an on or off state, it will not be in an invisible state.

Silverlight button style how to prevent the focused state when the button is pressed?

In my custom button I need to show that it had focus(provides some tactile feel to tabbing to the button) and show that its pressed but what I have found is my focused state is displaying rather then my pressed state. How can I correct this. I would like to have mouse over to pressed not mouse over then focused(when the button is clicked )
Here is a sample of my control template.
<UserControl.Resources>
<Style x:Key="GavelButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="#FF000000" x:Name="grid">
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Unfocused"/>
<vsm:VisualState x:Name="Focused">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="image" Storyboard.TargetProperty="(UIElement.OpacityMask).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="00:00:00" Value="#FFFFFFFF"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="grid" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="00:00:00" Value="#FF2844B9"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualStateGroup.Transitions>
<vsm:VisualTransition GeneratedDuration="00:00:00.2000000"/>
</vsm:VisualStateGroup.Transitions>
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="image" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="image" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1.5"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="image" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.5"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="image" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.5"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Disabled"/>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Image Cursor="Hand" x:Name="image" RenderTransformOrigin="0.5,0.5" Source="11_64x64.png" Stretch="Fill" OpacityMask="#FF000000">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>;
When you press it is becomes focused, can't do anything about that...you can clear the Visual State Manager's Focus content and then it won't look focused, but it get focus from the mouse interaction no matter what you do.
I've had success setting IsTabStop to False. I wouldn't expect it to prevent focus after clicking but that appears to be what it does. After clicking the button, the space bar is not captured.

Resources