Настройка VS2012, например, анимация окна WPF SizeToContent

Я пытаюсь добиться той же анимации, что и в окне настройки VS2012, автоматически меняя размеры и центрируясь при каждом изменении размера контента.

Проблема в том, что это не может быть сделано чисто кодом, так как я не знаю окончательный размер окна (для чего я полагаюсь на SizeToContent="WidthAndHeight"), но позволение SizeToContent = "WidthAndHeight" самостоятельно не позволяет мне оживить переход

Есть ли способ сделать это?

1 ответ

Решение

Я думаю, что самый простой способ достичь этого - использовать пользовательские визуальные состояния в вашем классе окна. Я сделал небольшой тестовый проект, который вы можете скачать здесь: https://dl.dropboxusercontent.com/u/14810011/ResizingWindow.zip

Вам нужно Visual Studio 2012, чтобы выполнить его.

Главное окно XAML выглядит так:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ResizingWindow"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    x:Name="Window" x:Class="ResizingWindow.MainWindow"
    Title="MainWindow" Width="350" Height="300" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Window.DataContext>
    <local:MainWindowViewModel />
</Window.DataContext>
  <Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="ExtendedStates">
            <VisualStateGroup.Transitions>
                <VisualTransition GeneratedDuration="0:0:0.6">
                    <VisualTransition.GeneratedEasingFunction>
                        <CubicEase EasingMode="EaseOut"/>
                    </VisualTransition.GeneratedEasingFunction>
                </VisualTransition>
            </VisualStateGroup.Transitions>
            <VisualState x:Name="Normal">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="TextBlock">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                    </DoubleAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="Window">
                        <EasingDoubleKeyFrame KeyTime="0" Value="300"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
            <VisualState x:Name="Extended">
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="Window">
                        <EasingDoubleKeyFrame KeyTime="0" Value="400"/>
                    </DoubleAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="TextBlock">
                        <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid.RowDefinitions>
        <RowDefinition Height="300"/>
        <RowDefinition Height="100"/>
    </Grid.RowDefinitions>
    <Border Background="#FF6C6C6C">
        <Grid>
            <TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="Hey, I here is some really cool content." VerticalAlignment="Top" FontSize="32" FontFamily="Segoe UI Light" TextAlignment="Center" Margin="0,50,0,0"/>
            <CheckBox Content="I want to see more" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,15" IsChecked="{Binding ShowAdditionalContent}">
                <i:Interaction.Behaviors>
                    <ei:DataStateBehavior Binding="{Binding ShowAdditionalContent}" Value="False" TrueState="Normal" FalseState="Extended"/>
                </i:Interaction.Behaviors>
            </CheckBox>
            <Button Content="&#xE221;" HorizontalAlignment="Right" VerticalAlignment="Top" FontFamily="Segoe UI Symbol" FontSize="21.333" Style="{DynamicResource ButtonStyle}" Margin="0,5,5,0" Click="CloseMainWindow"/>
        </Grid>
    </Border>
    <Border Grid.Row="1" Background="#FF383838">
        <TextBlock x:Name="TextBlock" TextWrapping="Wrap" Text="You can see this, when the check box is activated." FontFamily="Segoe UI Light" FontSize="18.667" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Silver"/>
    </Border>
  </Grid>
</Window>

Аспекты, на которые вы должны обратить внимание:

  • Главное окно состоит из сетки, вторая строка которой по умолчанию скрыта. Это достигается путем установки высоты окна на 300, в то время как сетка фактически использует 400 логических единиц. Можно также рассчитать эту высоту динамически во время выполнения, но для этого простого примера это не обязательно.
  • Второй ряд становится видимым, когда активировано "Расширенное" визуальное состояние. На самом деле это делается с помощью флажка, который обновляет соответствующую модель представления и прикрепленный DataStateBehavior (это часть Blend SDK), который отвечает на него. Когда состояние изменяется, это поведение гарантирует, что соответствующее визуальное состояние активировано, то есть "Нормальное", когда флажок снят, и "Расширенное", когда оно установлено.
  • WindowStyle установлен в None и ResizeMode установлен в NoResize, Это гарантирует, что вокруг окна не отображается граница. Также есть возможность установить AllowTransparency в true но я бы не рекомендовал это, поскольку это имеет некоторые серьезные последствия для производительности. Обратите внимание, что кнопки "Свернуть", "Развернуть / Восстановить" и "Выйти" по умолчанию также не будут присутствовать в этом режиме.

Пожалуйста, не стесняйтесь спрашивать, если у вас есть дополнительные вопросы.

Другие вопросы по тегам