1

I have a loading indicator that looks like this:

The spinning inidicator

Now I made it spin using a storyboard and it works fine. As far as I understood the animation in WPF, once the visual is collapsed/hidden the animation does not take any more resources (eg. the spinning).

But I realized, that even when it's collapsed it's still using a lot CPU power. Here is the code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        DataContext = new Vm();
        InitializeComponent();

    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Spinner.Visibility = Visibility.Collapsed;
    }
}

internal class Vm
{
    public Vm()
    {
        for (int i = 0; i < 5000; i++)
        {
            Items.Add(new Item());
        }
    }

    public List<Item> Items { get; } = new List<Item>();
}

public class Item { }

XAML:

<Window x:Class="test.MainWindow"
    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:local="clr-namespace:test"
    xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.Resources>
    <SolidColorBrush x:Key="THEME_LoadingSpinnerBackgroundBrush"
                 Color="#ebf0f5"
                 PresentationOptions:Freeze="True"/>
    <LinearGradientBrush x:Key="THEME_LoadingSpinnerForegroundBrush"
                     PresentationOptions:Freeze="True"
                     StartPoint="0,0"
                     EndPoint="1,0">
        <GradientStop Color="Red"   Offset="0"/>
        <GradientStop Color="White" Offset="0.5"/>
        <GradientStop Color="#000f789b" Offset="0.9"/>
    </LinearGradientBrush>

    <Storyboard x:Key="LoadingIndicatorStoryBoard"
            PresentationOptions:Freeze="True">
        <DoubleAnimation Storyboard.TargetName="icon"
                         Storyboard.TargetProperty="(Canvas.RenderTransform).(RotateTransform.Angle)"
                         From="0"
                         To="360"
                         Duration="00:00:1.3"
                         RepeatBehavior="Forever" />
    </Storyboard>

    <Style TargetType="{x:Type local:LoadingIndicator}">
        <Setter Property="Focusable"
            Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:LoadingIndicator}">
                    <Grid Width="20"
                          Height="20">
                        <Canvas x:Name="icon">
                            <Ellipse Canvas.Left="0"
                                     Canvas.Top="0"
                                     Width="20"
                                     Height="20"
                                     StrokeThickness="2"
                                     Stroke="{StaticResource THEME_LoadingSpinnerBackgroundBrush}"
                                     StrokeMiterLimit="4"/>
                            <Ellipse Canvas.Left="0"
                                     Canvas.Top="0"
                                     Width="20"
                                     Height="20"
                                     StrokeThickness="2"
                                     Stroke="{StaticResource THEME_LoadingSpinnerForegroundBrush}"
                                     StrokeMiterLimit="4"
                                     StrokeDashArray="17 25"/>
                            <Canvas.RenderTransform>
                                <RotateTransform CenterX="10"
                                                 CenterY="10"/>
                            </Canvas.RenderTransform>
                        </Canvas>
                        <Grid.Triggers>
                            <EventTrigger RoutedEvent="Loaded">
                                <BeginStoryboard Storyboard="{StaticResource LoadingIndicatorStoryBoard}"/>
                            </EventTrigger>
                        </Grid.Triggers>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>
<DockPanel>
    <Button DockPanel.Dock="Top" 
            Content="hide"
            Click="Button_Click"></Button>
    <ItemsControl ItemsSource="{Binding Items}"
                  Name="Spinner">
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type local:Item}">
                <local:LoadingIndicator />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</DockPanel>

CPU is at 10% on an almost empty window:

CPU is at 10% on an almost empty window

Can anyone tell me why the CPU usage won't go down?

5
  • If you're considering voting to close, I’d really appreciate it if you could let me know what additional details or clarifications would help make the problem clearer. Thank you Commented Jan 22 at 11:04
  • Besides that you haven't asked any question, what makes you think that animations would stop on collapsed elements? See e.g. stackoverflow.com/q/2333144/1136211. Commented Jan 22 at 11:49
  • Fair enough, I thought that's kinda obvious, but you're right. I added the question. Also, as far as I understand the animation system will continue to animate, but the rendering, eg. the layout should stop measuring and arranging the controls, right? Commented Jan 22 at 12:28
  • You are animating the RenderTransform property. That won't result in any layout cycles. Commented Jan 22 at 12:35
  • Fun fact: hit a breakpoint while debugging ... the Storyboards keep running. The StoryBoard stops when it reaches its "duraction" (completed event) (which is never for forever); or you "Stop()" it. Even when it has reached the end; it's not actually "stopped" (it's more on hold). "Stopping" it then, "syncs" things up. Or not; depends on what you're animating. Commented Jan 22 at 18:15

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.