11

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.

Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68
Debhere
  • 1,055
  • 2
  • 19
  • 41
  • If you want to learn about the process, read this article: http://blog.jerrynixon.com/2015/06/lets-code-build-custom-progress-ring-in.html – Jerry Nixon Nov 10 '15 at 16:10

2 Answers2

12

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.

Stewbob
  • 16,759
  • 9
  • 63
  • 107
  • I Think I need to use the ` ... ` inside the `Grid` control. But how do I trigger the animation? The animation does not seems to start, Do I need to write any code in xaml.cs ? – Debhere Mar 19 '14 at 16:24
  • 1
    In the example, the animation triggers as soon as the Path object is loaded, which doesn't happen in design view (you have to run the window this is placed on to see the animation). `` You can trigger the animations from pretty much any event you want, either by using XAML or using code. – Stewbob Mar 19 '14 at 16:38
  • your example is working perfectly, but after a complete rotation it stops. Any idea why its stopping? `RepeatBehaviour` is `Forever` but still it stops. after a rotation of 270 degree. – Debhere Mar 21 '14 at 06:23
  • 1
    Not sure why it would be stopping. On my screen the lead circle rotates 360 deg in 2 seconds, then pauses for 1 second, while the others catch up. Then repeats forever. – Stewbob Mar 21 '14 at 10:50
  • Works great for me, thanks for your work on making this control. – Physikbuddha Sep 24 '15 at 11:35
  • This is great! My OCD can't go past the fact that it doesn't lead to perfect circles though, they look a bit oval in shape. – johnildergleidisson Jul 20 '23 at 20:34
7

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

Community
  • 1
  • 1
Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68