【问题标题】:VS2012 Setup like WPF window animated SizeToContentVS2012 设置像 WPF 窗口动画 SizeToContent
【发布时间】:2013-04-21 10:13:44
【问题描述】:

我正在尝试实现与 VS2012 设置窗口相同的动画,以一种很好的动画方式自动调整大小并以每个内容大小变化为中心。

问题是它不能纯粹通过代码来完成,因为我不知道最终的窗口大小(因为我依赖 SizeToContent="WidthAndHeight"),但让 SizeToContent="WidthAndHeight" 由它自己做不允许我为过渡设置动画

有什么办法吗?

【问题讨论】:

    标签: wpf animated sizetocontent


    【解决方案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 设置为NoneResizeMode 设置为NoResize。这可确保窗口周围不显示边框。还有将AllowTransparency 设置为true 的选项,但我不建议这样做,因为这会对性能产生严重影响。请注意,默认的最小化、最大化/恢复和退出按钮也不会出现在此模式中。

    如果您还有其他问题,请随时提出。

    【讨论】:

    • 现在有点复杂了。想象一下,我不知道转换前的最终(在 SizeToContent 之后)窗口大小,因为它将取决于加载的数据。 “这是通过将窗口高度设置为 300 来实现的,而网格实际上使用 400 个逻辑单元。也可以在运行时动态计算这个高度,但是对于这个简单的例子,这不是必需的”我如何在运行时计算这个?
    • 一种解决方案是覆盖MainWindow.MeasureOverride 方法。在其中,只需执行这行代码var size = base.MeasureOverride(availableSize); 和瞧,你就得到了你孩子想要的大小。在这种情况下,我不建议使用视觉状态来制作情节提要,而是在代码中创建它们然后启动它们。您可以在 MSDN (msdn.microsoft.com/en-us/library/…) 上阅读更多关于 WPF 布局系统的措施和安排通道的信息。
    猜你喜欢
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 2012-11-03
    • 2016-07-23
    • 2011-01-09
    相关资源
    最近更新 更多