Wpf 如何在动画期间使框架元素保持在中间?

Wpf 如何在动画期间使框架元素保持在中间?,wpf,Wpf,我尝试制作一个位于窗口顶部中心的工具栏 在运行期间,工具栏的宽度可能会更改。我希望借助视觉状态(对我来说非常实用)和动画(使用关键帧)触发宽度 为了尽可能简化问题,我在窗口中放置了一个DockPanel,其中包含: 包含两个按钮(从一种视觉状态切换到另一种视觉状态)的堆叠面板 将由添加到其ControlTemplate的两个VisualState设置动画的按钮 这里是这个窗口的截图 Xaml代码: <Window xmlns="http://schemas.microsoft.com/wi

我尝试制作一个位于窗口顶部中心的工具栏

在运行期间,工具栏的宽度可能会更改。我希望借助视觉状态(对我来说非常实用)和动画(使用关键帧)触发宽度

为了尽可能简化问题,我在窗口中放置了一个DockPanel,其中包含:

  • 包含两个按钮(从一种视觉状态切换到另一种视觉状态)的堆叠面板
  • 将由添加到其ControlTemplate的两个VisualState设置动画的按钮
  • 这里是这个窗口的截图

    Xaml代码:

    <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:is="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" x:Class="DockPanelIssue.MainWindow"
        Background="LightYellow"
        Title="MainWindow" Height="200" Width="400">
    <DockPanel Background="Blue" HorizontalAlignment="Center" VerticalAlignment="Top">
        <StackPanel Margin="5" DockPanel.Dock="Bottom" Background="Orange" Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Margin="5" Click="Show_Click" Content="Show"/>
            <Button Margin="5" Click="Hide_Click" Content="Hide"/>
        </StackPanel>
        <Button Margin="5" x:Name="theButton" Background="Yellow" HorizontalAlignment="Center" VerticalAlignment="Center">
            <Button.Template>
                <ControlTemplate TargetType="{x:Type Button}">
                    <ContentControl>
                        <VisualStateManager.CustomVisualStateManager>
                            <is:ExtendedVisualStateManager />
                        </VisualStateManager.CustomVisualStateManager>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup is:ExtendedVisualStateManager.UseFluidLayout="True">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition GeneratedDuration="0:0:3"/>
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="StateHide">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="Chrome">
                                            <DoubleKeyFrameCollection>
                                                <LinearDoubleKeyFrame KeyTime="0%" Value="200"/>
                                                <LinearDoubleKeyFrame KeyTime="50%" Value="150"/>
                                                <LinearDoubleKeyFrame KeyTime="100%" Value="100"/>
                                            </DoubleKeyFrameCollection>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="StateShow">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="Chrome">
                                            <DoubleKeyFrameCollection>
                                                <LinearDoubleKeyFrame KeyTime="0%" Value="100"/>
                                                <LinearDoubleKeyFrame KeyTime="50%" Value="150"/>
                                                <LinearDoubleKeyFrame KeyTime="100%" Value="200"/>
                                            </DoubleKeyFrameCollection>
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </Border>
                    </ContentControl>
                </ControlTemplate>
            </Button.Template>
            Animated Button
        </Button>
    </DockPanel>
    
    我们期待的是AnimatedButton(黄色的)在3秒内增加他的宽度,(并且停留在中间)。但结果是:

  • 实际上,宽度很小,我们点击隐藏按钮
  • 动画按钮立即向左移动
  • 动画按钮仍在左侧,宽度正在增加
  • 在动画结束之前,动画按钮仍在左侧
  • 动画完成后,动画按钮现在更高了,它又回到中间(呸!)
  • 开始和结束是我们想要的,但是过渡(2,3,4)是不正确的

    下面是一张图片,其中包含步骤1至5的屏幕截图,以及说明我们需要的图形:

    如何做到这一点

    如果我犯了错误,请告诉我

    还有一些我不太理解的观点:

  • 为什么当我点击“隐藏”时,按钮会变大(我原以为会变小)
  • 为什么两个动画中的一个不播放过渡
  • 为什么蓝色的DockPanel在动画过程中宽度如此之大,高度如此之低(似乎橙色的stackPanel在动画过程中被计算为停靠在右侧而不是底部)
  • public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
        private void Hide_Click(object sender, RoutedEventArgs e)
        {
            ExtendedVisualStateManager.GoToState(theButton, "StateHide", true);
        }
    
        private void Show_Click(object sender, RoutedEventArgs e)
        {
            ExtendedVisualStateManager.GoToState(theButton, "StateShow", true);
        }
    }