How to create a Progress Ring like Windows 8 Style in WPF?

14,534

Solution 1

Using MahApps.Metro would be much simpler, but given below is a simple Metro-like wait indicator showing how it would be done in XAML.

<Viewbox>
        <Canvas Width="50" Height="50"
                HorizontalAlignment="Left"
                VerticalAlignment="Top">
            <Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
                  Fill="#FFFFFFFF"
                  RenderTransformOrigin="0.5,0.83333">
                <Path.RenderTransform >
                    <RotateTransform x:Name="_rot1" Angle="0"/>
                </Path.RenderTransform>
                <Path.Triggers>
                    <EventTrigger RoutedEvent="Path.Loaded">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot1"
                                                               Storyboard.TargetProperty="Angle"
                                                               RepeatBehavior="Forever">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0" Value="360"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0">
                                        <EasingDoubleKeyFrame.EasingFunction>
                                            <PowerEase Power="1.3" EasingMode="EaseInOut"/>
                                        </EasingDoubleKeyFrame.EasingFunction>
                                    </EasingDoubleKeyFrame>
                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="0"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Path.Triggers>
            </Path>
            <Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
                  Fill="#DDFFFFFF"
                  RenderTransformOrigin="0.5,0.83333">
                <Path.RenderTransform>
                    <RotateTransform x:Name="_rot2" Angle="13"/>
                </Path.RenderTransform>
                <Path.Triggers>
                    <EventTrigger RoutedEvent="Path.Loaded">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot2"
                                                               Storyboard.TargetProperty="Angle"
                                                               RepeatBehavior="Forever">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0" Value="13"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="13"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:2.2" Value="-347">
                                        <EasingDoubleKeyFrame.EasingFunction>
                                            <PowerEase Power="1.3" EasingMode="EaseInOut"/>
                                        </EasingDoubleKeyFrame.EasingFunction>
                                    </EasingDoubleKeyFrame>
                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-347"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Path.Triggers>
            </Path>
            <Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
                  Fill="#BBFFFFFF"
                  RenderTransformOrigin="0.5,0.83333">
                <Path.RenderTransform>
                    <RotateTransform x:Name="_rot3" Angle="26"/>
                </Path.RenderTransform>
                <Path.Triggers>
                    <EventTrigger RoutedEvent="Path.Loaded">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot3"
                                                               Storyboard.TargetProperty="Angle"
                                                               RepeatBehavior="Forever">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0" Value="26"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="26"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:2.4" Value="-334">
                                        <EasingDoubleKeyFrame.EasingFunction>
                                            <PowerEase Power="1.3" EasingMode="EaseInOut"/>
                                        </EasingDoubleKeyFrame.EasingFunction>
                                    </EasingDoubleKeyFrame>
                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-334"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Path.Triggers>
            </Path>

            <Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
                  Fill="#99FFFFFF"
                  RenderTransformOrigin="0.5,0.83333">
                <Path.RenderTransform>
                    <RotateTransform x:Name="_rot4" Angle="39"/>
                </Path.RenderTransform>
                <Path.Triggers>
                    <EventTrigger RoutedEvent="Path.Loaded">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot4"
                                                               Storyboard.TargetProperty="Angle"
                                                               RepeatBehavior="Forever">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0" Value="39"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="39"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:2.6" Value="-321">
                                        <EasingDoubleKeyFrame.EasingFunction>
                                            <PowerEase Power="1.3" EasingMode="EaseInOut"/>
                                        </EasingDoubleKeyFrame.EasingFunction>
                                    </EasingDoubleKeyFrame>
                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-321"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Path.Triggers>
            </Path>
            <Path Data="M50,27.5 C50,24.23333 45,24.23333 45,27.5 C45,30.83333 50,30.83333 50,27.5"
                  Fill="#77FFFFFF"
                  RenderTransformOrigin="0.5,0.83333">
                <Path.RenderTransform>
                    <RotateTransform x:Name="_rot5" Angle="52"/>
                </Path.RenderTransform>
                <Path.Triggers>
                    <EventTrigger RoutedEvent="Path.Loaded">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="_rot5"
                                                               Storyboard.TargetProperty="Angle"
                                                               RepeatBehavior="Forever">
                                    <EasingDoubleKeyFrame KeyTime="0:0:0" Value="52"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="52"/>
                                    <EasingDoubleKeyFrame KeyTime="0:0:2.8" Value="-308">
                                        <EasingDoubleKeyFrame.EasingFunction>
                                            <PowerEase Power="1.3" EasingMode="EaseInOut"/>
                                        </EasingDoubleKeyFrame.EasingFunction>
                                        </EasingDoubleKeyFrame>
                                    <EasingDoubleKeyFrame KeyTime="0:0:3" Value="-308"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Path.Triggers>
            </Path>
        </Canvas>
    </Viewbox>

It's essentially the same Path object, a filled circle, used 5 times, at 5 different rotation angles and 5 different opacity values for the fill.

Doubtless, there is a more efficient way to do this, but this method shows the animation and timings, as well as the easing to give it more natural, less abrupt feel, when the circles spin around and stop.

Solution 2

Use ProgressRing from MahApps.Metro:

The ProgressRing control is styled after a similar control in Windows 8 to indicate activity rather than a percentage of progress completed.

Example:

<Controls:ProgressRing IsActive="True" />

To change the size of the rings, you need to set Width and Height. Also, you can set a different color for each ring and set the size less than the established. To do this and get this Control without install full MahApps.Metro pack, look at my previous answer:

Make the ProgressRing in MahApps.Metro Smaller

Share:
14,534
Debhere
Author by

Debhere

Love to Code and love to experiment with Windows Phone 8 and windows 8 Apps.

Updated on June 05, 2022

Comments

  • Debhere
    Debhere almost 2 years

    I want to show progress in my Desktop apps like Windows 8 ProgressRing. This type of progress is shown at times of installation or when Windows Start, but this control can be used in many applications as its very clean and modern, but I don't know how to achieve that. The progress ring image is here.

    Please see the image:

    enter image description here

    May I know how do I code for it may be in XAML or in Code? I have seen that in WPF ProgressRing control is not present, so I have to go to some custom control. Idea link or suggestions please how can I proceed.