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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/452988/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 19:57:44  来源:igfitidea点击:

What is the best way to slide a panel in WPF?

wpfperformancexamlanimation

提问by Kris Erickson

I have a fairly simple UserControl that I have made (pardon my Xaml I am just learning WPF) and I want to slide the off the screen. To do so I am animating a translate transform (I also tried making the Panel the child of a canvas and animating the X position with the same results), but the panel moves very jerkily, even on a fairly fast new computer. What is the best way to slide in and out (preferably with KeySplines so that it moves with inertia) without getting the jerkyness. I only have 8 buttons on the panel, so I didn't think it would be too much of a problem.

我有一个相当简单的用户控件(请原谅我的 Xaml,我只是在学习 WPF),我想将其滑出屏幕。为此,我正在对平移变换进行动画处理(我还尝试使面板成为画布的子项并以相同的结果为 X 位置设置动画),但即使在相当快的新计算机上,面板移动也非常不稳定。滑入和滑出的最佳方法是什么(最好使用 KeySplines,以便它可以惯性移动)而不会出现抖动。我的面板上只有8个按钮,所以我认为这不会有太大问题。

Here is the Xaml I am using, it runs fine in Kaxaml, but it is very jerky and slow (as well as being jerkly and slow when run compiled in a WPF app).

这是我正在使用的 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>

采纳答案by Kris Erickson

It looks like the best solution so far, is to use a Visual Brush and move two static images when sliding in and out the panels. Something similar to this is described in this blog post:

到目前为止,看起来最好的解决方案是使用 Visual Brush 并在滑入和滑出面板时移动两个静态图像。此博客文章中描述了与此类似的内容:

Using animated navigation pages in a WPF application(switched to web archive, but this is from 2008 so no promises if it is still the best technique).

在 WPF 应用程序中使用动画导航页面(切换到网络存档,但这是从 2008 年开始的,所以不能保证它是否仍然是最好的技术)。

回答by Drew Noakes

I've found WPF performance of animations to improve significantly when not using BitmapEffects. Try disabling them in your example. I replaced my drop shadows with semi-transparent solid regions with gradient fills and performance improved.

我发现不使用BitmapEffects时动画的 WPF 性能会显着提高。尝试在您的示例中禁用它们。我用带有渐变填充和性能改进的半透明实体区域替换了我的阴影。

I've also heard that some bitmap effects have increased performance in newer versions (maybe 3.5 SP1?) as more of the rendering has been pushed to the hardware.

我还听说一些位图效果在较新版本(可能是 3.5 SP1?)中提高了性能,因为更多的渲染已被推送到硬件。

回答by Dmitri Nesteruk

If you work with WPF animations long enough, you'll figure out that large-area controls do, in fact, move in a what you call 'jerky' manner. I've had this problem even with tiny buttons that needed to move horizontally on the screen, and I have certainly given up on moving anything large (e.g., a window).

如果您使用 WPF 动画的时间足够长,您会发现大区域控件实际上以您所谓的“生涩”方式移动。即使使用需要在屏幕上水平移动的小按钮,我也遇到了这个问题,我当然已经放弃移动任何大的东西(例如,一个窗口)。