Search code examples
c#wpfxamlvisualstatemanager

VisualStateManager wont change size of the window in wpf form


I have defined 2 states one Big and other Small and the big state will increase window size and small will reduce window size.

the window have a tab control and 2 tabitem. What I want to do is, to change the size of window to Big state when tab1 is selected and change the size of window to Small state when tab2 is selected. I wrote the following code but it is not working.

the following is XAML Code.

<Window x:Name="window" x:Class="WpfApp2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp2"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateGroup">
            <VisualStateGroup.Transitions>
                <VisualTransition From="Big" GeneratedDuration="0:0:1" To="Small"/>
                <VisualTransition From="Small" GeneratedDuration="0:0:1" To="Big"/>
            </VisualStateGroup.Transitions>
            <VisualState x:Name="Big">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="window">
                        <EasingDoubleKeyFrame KeyTime="0" Value="558.333"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="Small">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="window">
                        <EasingDoubleKeyFrame KeyTime="0" Value="290.152"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <TabControl HorizontalAlignment="Left" Height="319" VerticalAlignment="Top" Width="517" SelectionChanged="changes">
        <TabItem Header="TabItem" Name="tab1"/>
        <TabItem Header="TabItem" Name="tab2"/>
    </TabControl>

</Grid>

The following is the c# code.

 private void changes(object sender, SelectionChangedEventArgs e)
    {
        if (tab1.IsSelected)
        {
            VisualStateManager.GoToState(window, "Big", true);
        }
        else
        {
            VisualStateManager.GoToState(window, "Small", true);
        }
        i++;
    }

Solution

  • First move the VisualStateManager.VisualStateGroups attached property and its contents right below the root element (the Window).

    <Window x:Name="window" x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisualStateGroup">
                <VisualStateGroup.Transitions>
                    <VisualTransition From="Big" GeneratedDuration="0:0:1" To="Small"/>
                    <VisualTransition From="Small" GeneratedDuration="0:0:1" To="Big"/>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Big">
                    <Storyboard>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="window">
                            <EasingDoubleKeyFrame KeyTime="0" Value="558.333"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Small">
                    <Storyboard>
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="window">
                            <EasingDoubleKeyFrame KeyTime="0" Value="290.152"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    
        <Grid>
            <TabControl HorizontalAlignment="Left" Height="319" VerticalAlignment="Top" Width="517" SelectionChanged="changes">
                <TabItem Header="TabItem" Name="tab1"/>
                <TabItem Header="TabItem" Name="tab2"/>
            </TabControl>
    
        </Grid>
    </Window>
    

    And use GoToElementState method, instead of GoToState. Outside a ControlTemplate the GoToElementState method should be used.

    private void changes(object sender, SelectionChangedEventArgs e)
    {
        if (tab1.IsSelected)
        {
            VisualStateManager.GoToElementState(window, "Big", true);
        }
        else
        {
            VisualStateManager.GoToElementState(window, "Small", true);
        }
    }