MorgoZ
MorgoZ

Reputation: 2052

How to style a button with VisualStateManager

i want to define the style of some buttons of my WPF application at the Window level. Here is the code:

<Style x:Key="MainButtonStyle" TargetType="Button">
        <Setter Property="Width" Value="120"/>
        <Setter Property="Height" Value="60"/>
        <Setter Property="Margin" Value="5"/>
        <Setter Property="Background" Value="White"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid x:Name="ButtonGrid">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">

                                <VisualStateGroup.Transitions>
                                    <!--Take one half second to transition to the MouseOver state.-->
                                    <VisualTransition To="MouseOver" GeneratedDuration="0:0:0.5" />
                                </VisualStateGroup.Transitions>

                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimation Duration="0" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background" To="Cyan"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ColorAnimation Duration="0" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background" To="Red"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

What i want to do is to define some style properties of the button like Width or Color and also set a VisualState to stablish the behaviour of the button on Pressed, MouseOver, etc.

But that code does not work, because once the "Template" property is defined, all other properties (Width, Margin, etc) are forgotten, what is the proper way to make it work? Should i define all the button properties inside the "Grid" Properties of the Template?

Thank you.

EDIT: A SOLUTION. BUT I DON'T UNDERSTAND WHY

Ok, i have a solution, now it is working fine but i still don't understand why does WPF behaves this way. I'm new in this language and it is realy hard to know what property to work with in different Controls and how to implement it... I'm finding it zero intuitive in many cases... I hope it is just that i'm a newbie.

Any case, the problem was twice:

First: All the properties set by the "MainButtonStyle" works fine except the "Background", which seems to be overriden by the Grid at the ControlTemplate, so i had to set the BackGround property at the Grid in place of setting it at the Button... I don't finish to understand why is it happening.

Second: The "StoryBoard.TargetProperty="Background" can't be assigned to a Color object, i had to specify "StoryBoard.TargetProperty="BackGround.Color" to properly assign a Color object. And like before, i don't understand why. If in other Controls i can set the BackGround property directly to a Color value like "BackGround = "Red", why in a StoryBoard i have to set it "BackGround.Color="Red"?

Ok, now the code working:

<Style x:Key="MainButtonStyle" TargetType="Button">
        <Setter Property="Width" Value="120"/>
        <Setter Property="Height" Value="60"/>
        <Setter Property="Margin" Value="5"/>            
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid Background="White" x:Name="ButtonGrid">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>                                            
                                        <ColorAnimation Duration="0:0:0.3" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background.Color" To="Cyan"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background.Color" To="DarkSalmon"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

So, there is the solution, but if someone could explain better WHY, i would appreciate it.

Upvotes: 1

Views: 7191

Answers (1)

user2825546
user2825546

Reputation: 154

When you are defining a style for a control and you are also overriding the default control template the button no longer has its default layout. It only contains those elements you define in the control template. IN THE ABOVE CASE THE BUTTON ONLY CONTAINS ONE GRID.

Upvotes: 1

Related Questions