How to test VisualStateManager states? - wpf

How do I check the current states of a control? VisualStateManager allows me to set it from the control itself, but I can't see any way of reading it back?

If you have one group, or wants to find the state in a specific group you can do something like :
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Group1">
<VisualState x:Name="State1">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="State2">
<Storyboard>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
and in your code you can do something like :
var state = Group1.CurrentState;
Console.WriteLine(state.Name);

Related

wpf usercontrol states, modifying height

I am a little bit confused of states and animations in WPF.
I would like to make a usercontrol. This usercontrol will contains (inside the main grid) 2 another grid. One of them would be HEADER and second one will be CONTENT. If user click on header, content will expand, otherwise will be collapsed. And i would like to animation that expanding (Slide down the content from the header).
Basicaly i would like to do that by states (for future purpose). Problem is, if i add the states and i am using the slide efect with transformation, the content of this grid (CONTENT GRID) is transformed as well. So i would like to use the states with modifying just the height of the element. If u modify only the element, no animation appear and it just change its height at once.
The hierarchy looks like:
--- wrapper grid
------ header grid
--------- content of header
------ content grid
--------- content of content grid (like buttons, labels, etc)
The visualstates looks like:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:1"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Expanded"/>
<VisualState x:Name="Collapsed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<x:Double>0</x:Double>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Any advice to see the expanding and collapsing the grid with modifying height by states?
With animation only it works perfect, but its better for me to do it with states, how i said, for future purpose.
Maybe i found a answer. For now it works but i am trying to understanding that changes.
code of visualstates in here:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Expanded">
<Storyboard>
<DoubleAnimation EnableDependentAnimation="True" Storyboard.TargetName="grid" Storyboard.TargetProperty="(FrameworkElement.Height)" From="0" To="366" Duration="0:0:0.600" />
</Storyboard>
</VisualState>
<VisualState x:Name="Collapsed">
<Storyboard>
<DoubleAnimation EnableDependentAnimation="True" Storyboard.TargetName="grid" Storyboard.TargetProperty="(FrameworkElement.Height)" From="366" To="0" Duration="0:0:0.600" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
The important line is:
<DoubleAnimation EnableDependentAnimation="True" Storyboard.TargetName="grid" Storyboard.TargetProperty="(FrameworkElement.Height)" From="366" To="0" Duration="0:0:0.600" />
I found its needed to have EnableDependantAnimation true.
Now it works as a charm, but i do not like that FROM TO set. But its possibly the best i can do in here.

Animating the transition from Pressed to Normal button state

My Pressed state is lowering the opacity of the Button content.
I would like to animate the transition back from Pressed to Normal, so that it takes 3 seconds to happen. I tried defining a VisualTransition but it doesn't work. Pressing my button immediately goes back to Normal, I don't see the opacity gradually coming back from 0.5 to 1.
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="Pressed"
To="Normal"
GeneratedDuration="0:0:3" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0"
Value="0.5" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
I would like to know what I'm doing wrong.
Is it not working on phone or within dev environment using mouse?
If the latter, have you tried changing your VisualTransition to Pressed->MouseOver? With mouse it isn't possible to go from pressed->normal because mouse will still be the over.
Apart from that possibility, everything looks ok at first glance.
(A useful resource I've found is http://samples.msdn.microsoft.com/Silverlight/SampleBrowser/index.htm#/?sref=CustomTemplateSamples&id=4, which although for SilverLight should still be useful for WPF)

Binding and VisualStateManager do not work together

I have VisualStateManager to control when the State occurs, the control is enabled:
Here is the property of the state (string):
states:StateManager.VisualStateProperty="{Binding SomeProp}"
Here the VisualStateManager:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualState x:Name="MyName">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.IsEnabled)" Storyboard.TargetName="MyTextBox">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="HerName">
<Storyboard>
...
</Storyboard>
</VisualState>
<VisualState x:Name="This">
<Storyboard>
...
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Here my text box:
<TextBox Name="MyTextBox" />
My question is: What happens when I add the TextBox the following line:
IsEnable= {Binding isProp}// isProp = bool
The way I see it, it eliminates the IsEnable of the TextBox and not refers to him, only to State.
Is this true? And is there a way they both work?
In your case, the Animation will take precedence over the binding, but only as long as the Animation's timeline is running. That is, when the visual state is "MyName", the animation will control the IsEnabled property; otherwise, the binding will.
You may be interested in this list of Dependency Property Value Precedence. The binding counts as a "Local value" and is of lower precedence than the animation.

Silverlight, VisualStateManager gotostate doesn't work with datatemplates

I have a button with name "PART_closeButton" inside ContentPresenter. I am defining some visual states for my button.
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1"
Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PART_closeButton" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<DoubleAnimation Duration="0" To="0.7" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="PARTcloseButton" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
So everything is working for me. When I mouse over on button it becomes semitransparent.
But if I load some datatemplate for contentpresenter which also contains button with that same name, visual states does not react anymore. (mouseOver event is handled for that button also and it fires).
goToState is not working.
I know that actual button object is changing, VisualState is connected with button with TargetName. So new button have the same name, why statemanager is not working ?

Why is the ColorAnimation for Checked state not persisting color after the MouseOver state is triggered?

I encountered an issue with a ControlTemplate for ToggleButton I created.
When the button is Checked, a ColorAnimation is triggered and the control's background changes color. However, if the user enters the MouseOver state, another animation is triggered that affects the button's background as well.
When the mouse is no longer in the MouseOver state, the control does not return to the color it should be while it is in the Checked state. I'm not sure why this does not persist when the MouseOver state is triggered.
The VisualStateManager portion of my ControlTemplate looks sorta like this:
<VisualStateManger.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"></VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundBorder"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="Gold" Duration="0:0:0.3" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundBorder"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="PaleGoldenrod" Duration="0:0:0.3" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
My workaround for the issue I was having involved creating a Grid that enclosed the Border.
For the CommonStates I made animation changes to the Border.Background and for the CheckedStates I made animation changes to the Grid.Background.
It achieves the visual effect I was looking for.

Resources