MahApps / MahApps.Metro

A framework that allows developers to cobble together a better UI for their own WPF applications with minimal effort.
https://mahapps.com
MIT License
9.32k stars 2.45k forks source link

Choppy / jerky animation using Storyboard and DoubleAnimation in a MetroWindow #3432

Closed teekay closed 5 years ago

teekay commented 5 years ago

Issue description

I have a simple animation that I create programmatically. Say it's a vertical line moving along the X axis.

Using a "normal" WPF Window, it does so smoothly.

Using a MetroWindow, the animation is choppy - the line moves a pixel, stops for a few ms., then moves again.

Code sample

Window.xaml

<mah:MetroWindow x:Class="Animation.Alternative"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
        mc:Ignorable="d"
        Title="Test animation" Height="450" Width="800">
    <StackPanel Margin="0,200,0,0">
        <Canvas Width="600" Height="60" x:Name="Whiteboard"></Canvas>
        <Button HorizontalAlignment="Center"
                Margin="0,20,0,0"
                Click="RunTestAnimation">Run Test</Button>
    </StackPanel>
</mah:MetroWindow>

Window.xaml.cs

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Animation
{
    public partial class Alternative
    {
        public Alternative()
        {
            InitializeComponent();
        }

        private readonly Storyboard _trackProgressAnimationBoard = new Storyboard();
        private readonly Line _progressLine = new Line();

        private void RunTestAnimation(object sender, RoutedEventArgs e)
        {
            double sourceX = 0;
            double targetX = Whiteboard.ActualWidth;

            _progressLine.X1 = sourceX;
            _progressLine.X2 = sourceX;
            _progressLine.Y1 = 10.0d;
            _progressLine.Y2 = Whiteboard.RenderSize.Height;
            _progressLine.Stroke = new SolidColorBrush(Color.FromRgb(255, 25, 20));
            Whiteboard.Children.Add(_progressLine);

            var duration = TimeSpan.FromSeconds(180);
            var lineAnimationX1 = new DoubleAnimation(sourceX, targetX, duration);
            var lineAnimationX2 = new DoubleAnimation(sourceX, targetX, duration);

            _trackProgressAnimationBoard.Children.Clear();
            _trackProgressAnimationBoard.Children.Add(lineAnimationX1);
            _trackProgressAnimationBoard.Children.Add(lineAnimationX2);
            _trackProgressAnimationBoard.Duration = duration;            

            Storyboard.SetTarget(lineAnimationX1, _progressLine);
            Storyboard.SetTarget(lineAnimationX2, _progressLine);
            Storyboard.SetTargetProperty(lineAnimationX1, new PropertyPath("(Line.X1)"));
            Storyboard.SetTargetProperty(lineAnimationX2, new PropertyPath("(Line.X2)"));

            _trackProgressAnimationBoard.Begin(this, true);
        }
    }
}

Environment

punker76 commented 5 years ago

@teekay We set the UseLayoutRounding for the inner ContentPresenter to false for better results, so to bring back the same as without MahApps just set this to true for your StackPanel (I got the same result as without MahApps)

<StackPanel Margin="0,200,0,0" UseLayoutRounding="True">
    <Canvas Width="600" Height="60" x:Name="Whiteboard"></Canvas>
    <Button HorizontalAlignment="Center"
            Margin="0,20,0,0"
            Click="RunTestAnimation">Run Test</Button>
</StackPanel>