I am working on a WPF application and trying to make a responsive UI using Visual State Manager as MSDN suggests for UWP responsive design and it works on UWP but not on WPF.
Here is the example I am testing on WPF. It is supposed to change the background of the StackPanel
to Red
on start-up.
The XAML:
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultState">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="WideState">
<Storyboard >
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Menu" Storyboard.TargetProperty="StackPanel.Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Red"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="*"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Grid x:Name="StackPanelCenetrofPage" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="MenuColumnWidth" Width="200"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="Menu"
Orientation="Vertical"
Background="AliceBlue"
HorizontalAlignment="Stretch"
Grid.Column="0">
<Button Content="Hey"/>
</StackPanel>
<Frame Grid.Column="1"/>
</Grid>
</Grid>
And the C# code:
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.PreviousSize.Width < 1024)
{
VisualStateManager.GoToState(this, "WideState", true);
}
else
{
VisualStateManager.GoToState(this, "DefaultState", false);
}
}
According to the documentation:
Call the GoToState method if you are changing states in a control that uses the VisualStateManager in its ControlTemplate. Call the GoToElementState method to change states on an element outside of a ControlTemplate (for example, if you use a VisualStateManager in a UserControl or in a single element).
So you should use GoToElementState
instead of GoToState
. The first parameter of GoToElementState
is the control owning the VisualStateManager
so you should move the VisualStateManager
to the Window
to keep using this
in the code-behind.
private void Window_SizeChanged(object sender, SizeChangedEventArgs e) {
if (e.PreviousSize.Width < 1024) {
var result = VisualStateManager.GoToElementState(this, "WideState", true); // <- Here
} else {
VisualStateManager.GoToElementState(this, "DefaultState", false);
}
}
On a side note, you cannot animate the Background
like this. You need to define a Value
that is a Brush
and not just a Color
:
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Red"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>