什么是在WPF中滑动面板的最佳方法?

11

我有一个相当简单的UserControl(请忽略我的Xaml,我正在学习WPF),我想把它滑到屏幕外。 为此,我正在使用动画移动translate transform(我还尝试将Panel作为Canvas的子级并使用相同结果动画化X位置),但面板移动得很卡顿,即使在一台相当快的新计算机上也是如此。 最好的方法是如何滑入和滑出(最好使用KeySplines,以便具有惯性运动)而不会产生颤动。 我的面板上只有8个按钮,所以我认为这不应该是太大的问题。

下面是我使用的Xaml,在Kaxaml中可以正常运行,但在WPF应用程序中编译后非常卡顿和缓慢。

  <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="1002" Height="578">
     <UserControl.Resources>            
        <Style TargetType="Button">
           <Setter Property="Control.Padding" Value="4"/>
           <Setter Property="Control.Margin" Value="10"/>
           <Setter Property="Control.Template">
              <Setter.Value>
                 <ControlTemplate TargetType="Button">
                    <Grid Name="backgroundGrid" Width="210" Height="210" Background="#00FFFFFF">
                       <Grid.BitmapEffect>
                          <BitmapEffectGroup>
                             <DropShadowBitmapEffect x:Name="buttonDropShadow" ShadowDepth="2"/>
                             <OuterGlowBitmapEffect x:Name="buttonGlow" GlowColor="#A0FEDF00" GlowSize="0"/>
                          </BitmapEffectGroup>
                       </Grid.BitmapEffect>
                       <Border x:Name="background" Margin="1,1,1,1" CornerRadius="15">
                          <Border.Background>
                             <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                <LinearGradientBrush.GradientStops>
                                   <GradientStop Offset="0" Color="#FF0062B6"/>
                                   <GradientStop Offset="1" Color="#FF0089FE"/>
                                </LinearGradientBrush.GradientStops>
                             </LinearGradientBrush>
                          </Border.Background>
                       </Border>
                       <Border Margin="1,1,1,0" BorderBrush="#FF000000" BorderThickness="1.5" CornerRadius="15"/>
                       <ContentPresenter HorizontalAlignment="Center" Margin="{TemplateBinding Control.Padding}" 
                        VerticalAlignment="Center" Content="{TemplateBinding ContentControl.Content}" 
                        ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"/>
                    </Grid>
                 </ControlTemplate>
              </Setter.Value>
           </Setter>
        </Style>
     </UserControl.Resources>
     <Canvas>
        <Grid x:Name="Panel1" Height="578" Canvas.Left="0" Canvas.Top="0">
           <Grid.RenderTransform>
              <TransformGroup>
                 <TranslateTransform x:Name="panelTranslate" X="0" Y="0"/>
              </TransformGroup>
           </Grid.RenderTransform>
           <Grid.RowDefinitions>
              <RowDefinition Height="287"/>
              <RowDefinition Height="287"/>
           </Grid.RowDefinitions>
           <Grid.ColumnDefinitions>
              <ColumnDefinition x:Name="Panel1Col1"/>
              <ColumnDefinition x:Name="Panel1Col2"/>
              <ColumnDefinition x:Name="Panel1Col3"/>
              <ColumnDefinition x:Name="Panel1Col4"/>
     <!-- Set width to 0 to hide a column-->
           </Grid.ColumnDefinitions>
           <Button x:Name="Panel1Product1" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
              <Button.Triggers>
                 <EventTrigger RoutedEvent="Button.Click" SourceName="Panel1Product1">
                    <EventTrigger.Actions>
                       <BeginStoryboard>
                          <Storyboard>
                             <DoubleAnimation BeginTime="00:00:00.6" Duration="0:0:3" From="0" Storyboard.TargetName="panelTranslate" Storyboard.TargetProperty="X" To="-1000"/>
                          </Storyboard>
                       </BeginStoryboard>
                    </EventTrigger.Actions>
                 </EventTrigger>
              </Button.Triggers>
           </Button>
           <Button x:Name="Panel1Product2" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
           <Button x:Name="Panel1Product3" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
           <Button x:Name="Panel1Product4" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
           <Button x:Name="Panel1Product5" Grid.Column="2" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
           <Button x:Name="Panel1Product6" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
           <Button x:Name="Panel1Product7" Grid.Column="3" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
           <Button x:Name="Panel1Product8" Grid.Column="3" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
     </Canvas>
  </UserControl>
3个回答

10
目前看来最好的解决方案似乎是使用Visual Brush,在滑动面板时移动两个静态图像。类似于这篇博客文章中描述的内容:在WPF应用程序中使用动画导航页面(已切换到Web Archive,但这是2008年的内容,不能保证它仍然是最佳技术)。

1
抱歉,所提到的链接已经失效:错误404 - 未找到。 - Junior Mayhé
2
对我有用。转到JAPF-博客存档:“在WPF应用程序中使用动画导航页面”。 - Padu Merloti
1
@PaduMerloti 在Junior发表评论后,链接已经修复。将相关的代码片段/解释放在答案中会更有效地对抗链接失效问题。 - Asad Saeeduddin
链接现在尝试显示,但由于其PHP代码中的致命错误而无用。 - ToolmakerSteve

5
我发现在不使用BitmapEffect时,WPF动画的性能显著提高。请尝试在您的示例中禁用它们。我用半透明实心区域和渐变填充替换了我的投影阴影,性能得到了改善。
我还听说一些位图效果在较新版本(可能是3.5 SP1?)中具有更高的性能,因为更多的渲染已经被推送到硬件上。

4

如果您长时间使用WPF动画,您会发现大面积控件的移动确实是以所谓的“抖动”方式进行的。即使是需要在屏幕上水平移动的小按钮,我也遇到了这个问题,而且我肯定放弃了移动任何大型控件(例如窗口)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接