Reputation: 32984
I've a button control that's got 2 visual states; say "Simple" and "Complex"; the former being the default. Initially the control is hidden.
When I set the visual state through VisualStateManager to "Complex", I get false
, but when I make the control visible once and then set the visual state, it returns true
and the state is preserved (even after the control becoming invisible) i.e. all that matters is if the control was shown atleast once; if so, the visual state changes are respected, else it's always ignored until it's shown once.
How do I set the visual state for a control that's yet to be visible?
<Grid x:Name="LayoutRoot"
Background="LightBlue">
<Grid.Resources>
<Style x:Key="MyButton"
TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MyStates">
<VisualState x:Name="Simple" />
<VisualState x:Name="Complex">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ellipse"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<DiscreteObjectKeyFrame KeyTime="10"
Value="#00000000" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse x:Name="ellipse"
Fill="#FF0E0EF5"
Stroke="Black" />
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Button x:Name="btnStuff"
Content="Click Me!"
Visibility="Collapsed"
Style="{StaticResource MyButton}" />
<StackPanel>
<Button x:Name="btnShow"
Content="Show"
Click="btnShow_Click" />
<Button x:Name="btnVisual"
Content="Visual Change"
Click="btnVisual_Click" />
</StackPanel>
</Grid>
Code behind:
bool fOriginalState = true;
private void btnShow_Click(object sender, RoutedEventArgs e)
{
btnStuff.Visibility = btnStuff.Visibility == Windows.UI.Xaml.Visibility.Visible ? Windows.UI.Xaml.Visibility.Collapsed : Windows.UI.Xaml.Visibility.Visible;
}
private void btnVisual_Click(object sender, RoutedEventArgs e)
{
string visualState = fOriginalState ? "Complex" : "Simple";
fOriginalState = !fOriginalState;
bool fSet = VisualStateManager.GoToState(btnStuff, visualState, false);
System.Diagnostics.Debug.WriteLine(fSet.ToString());
}
Upvotes: 1
Views: 1816
Reputation: 32984
MSDN says
It is also appropriate to call the VisualStateManager.GoToState method from a Loaded handler in order to set an initial view state that is defined in the template.
under the FrameworkElement.Loaded
event handler page; however, setting the required visual state here too gets ignored if Visibility="Collapsed"
was hardcoded in the XAML.
The reason behind this issue is, when a control's Visibility
was set to Collapsed
right from the beginning of the app. then it never gets loaded; it's deferred until the property is set to Visible
during runtime; once it's set, then it does get loaded, there by making the control appear in the VisualTree. Before appearing in the visual tree, any visual state change requests for a control gets neglected.
The work around I've found is to not set the control to Collapsed
in XAML; since the control is visible, it gets loaded and in the loaded event handler, one can set the Visibility
to Collapsed
, all calls to VSM.GotoState would get honoured since the control is already in the VisualTree now.
Hope this helps someone who's fumbling around for a solution like me.
Upvotes: 4