Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / XAML

How to Create a Circular Loader using XAML?

5.00/5 (4 votes)
22 Jul 2011CPOL6 min read 18.4K  
How to create a circular loader using XAML?

Circular Loader

Sometimes, we need to show a circular loader in WPF and/or Silverlight. We may need it in Windows Phone 7 too. In simple statement, we need to show a circular loader in various XAML applications like Silverlight, WP7 and WPF.

In this article, we will learn how to create a Circular Loader as shown in the screenshot. I will not use a single line of C# code to create this loader. Everything will be in the XAML file itself to keep the code behind file clean. Read to know more about it step-by-step and after reading this article, you will be able to create and use a circular loader like this. The source code is also available for download at the end of the page. Feel free to use it.

Setup the Project

First, we need to create a Silverlight project. Here, we will create a Silverlight 4 Application project. Once you are done with the project creation, right click on the Silverlight project and add a new UserControl. We will use this as the circular loader. As shown in the below screenshot, select the "Silverlight User Control" template and provide a name "CircularLoader.xaml" and hit "Add" to continue.

Loader Demo - Create a new UserControl called CircularLoader.xaml

This will create a new UserControl in your solution project. Once done with this step, it's time to create the UI of the loader control. Then, we will integrate it to the MainPage.xaml and see how it looks.

Create the UI of the Circular Loader

Now time to create the XAML of the loader. Remember that we will not have a single line of C# code. Everything will be done in the XAML. If you are an expert with Expression Blend, you can create it very easily. But here, we will use direct XAML code to demonstrate the same. It will be helpful for you to understand properly.

Let's open the usercontrol XAML file and replace the original Grid control with a ViewBox control. You may ask one question here: Why should I use a ViewBox? Yes my friend, a very good question. ViewBox will allow you to resize the content of the panel with respect to parent container. This means if you explicitly increase or decrease the size of the user control, the inner content will proportionally resize as per the container size.

Now we will add a Canvas inside the ViewBox so that we can properly place the circles inside it in proper (x, y) coordinates.

After this step, we need to add some Ellipse control inside the Canvas panel to create a Circle. We will fill the color of the Ellipse with the Foreground color of the UserControl. We will use proper binding to do this, as shown below:

XML
<Ellipse Fill="{Binding Foreground, 
ElementName=userControl}" 
        Height="71" Canvas.Left="121" 
        Canvas.Top="21" Width="69" Opacity="0.3"/>

In the above code snippet, you can see that we added Canvas.Left and Canvas.Top to position the circle. Similarly, we will add some more circles using the Ellipse control and position them properly to create a circular path.

Setting the Opacity of the Circles

We need to set the opacity of the circles to create the similar look as we wanted to develop. Opacity will ensure that we will use the same color but different transparency to create the UI.

Find the below XAML code for reference:

Loader Demo - Designing the Loader Circles with Proper Opacity Value

Have a look into the above XAML code. You will see there how we placed the circles in proper coordinate positions. Also check the opacity that we set for each individual circles.

Adding RenderTransform to the Canvas

Once you are done with the UI, you need to set the RenderTransform to the canvas. This step is required to keep the circle rotating in the orbit. We will add a composite transform to the canvas as shown below:

Loader Demo - Adding RenderTransform to the Canvas

Our animation that we will create in the next step will use the same transform of the canvas to rotate the circles in the circular orbit.

Find the complete code of the UI here, in case you need proper visibility on the code that we created just now:

XML
<Viewbox x:Name="LayoutRoot" 
HorizontalAlignment="Left" VerticalAlignment="Top">
   <Canvas x:Name="canvas" Height="323" 
   Width="308" RenderTransformOrigin="0.5,0.5">
        <Canvas.RenderTransform>
           <CompositeTransform/>
        </Canvas.RenderTransform>
       <Ellipse Fill="{Binding Foreground, ElementName=userControl}" 
                 Height="71" Canvas.Left="121" 
                 Canvas.Top="21" Width="69" Opacity="0.3"/>
       <Ellipse Fill="{Binding Foreground, ElementName=userControl}" 
                 Height="71" Width="69" 
                 Canvas.Left="194" Canvas.Top="52" Opacity="0.4"/>
       <Ellipse Fill="{Binding Foreground, ElementName=userControl}" 
                 Width="69" Height="71" 
                 Canvas.Left="221" 
                 Canvas.Top="123" Opacity="0.5"/>
       <Ellipse Fill="{Binding Foreground, 
       ElementName=userControl}" 
                 Width="69" Height="71" 
                 Canvas.Left="190" Canvas.Top="198" 
                 Opacity="0.6"/>
       <Ellipse Fill="{Binding Foreground, ElementName=userControl}" 
                 Height="71" Canvas.Left="121" 
                 Canvas.Top="226" Width="69" 
                 Opacity="0.7"/>
       <Ellipse Fill="{Binding Foreground, ElementName=userControl}" 
                 Width="69" Height="71" 
                 Canvas.Left="48" Canvas.Top="194" 
                 Opacity="0.8"/>
       <Ellipse Fill="{Binding Foreground, ElementName=userControl}" 
                 Height="71" Width="69" 
                 Canvas.Left="17" Canvas.Top="123" 
                 Opacity="0.9"/>
       <Ellipse Fill="{Binding Foreground, ElementName=userControl}" 
                 Height="71" Width="69" 
                 Canvas.Left="48" Canvas.Top="52" Opacity="1.0"/>
   </Canvas>
</Viewbox>

Create the Storyboard

Now what do we need in this step? We need to create a smooth animation which we can achieve using the StoryBoard. We will create a Storyboard now to rotate the circles in the orbit. You can use the Expression Blend to create the animation easily. As this is a simpler code, I am just sharing the code for you here:

XML
<UserControl.Resources>
   <Storyboard x:Name="LoaderAnimation">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=
           "(UIElement.RenderTransform).(CompositeTransform.Rotation)" 
                                      Storyboard.TargetName="canvas" 
                                       RepeatBehavior="Forever">
           <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
            <EasingDoubleKeyFrame KeyTime="0:0:3" Value="360"/>
       </DoubleAnimationUsingKeyFrames>
    </Storyboard>
 
</UserControl.Resources>

The storyboard will rotate the canvas to 360 degree to give a circular motion to the circles. Also, we will set the RepeatBehavior to indefinite by setting the value "Forever". Here, the storyboard will be available as a Resource to the UserControl. Hence, we can easily access it whenever required.

Once the storyboard has been created, we need to run it on load. The simplest approach here will be calling the Begin() method of the storyboard from code behind class. As I told, we will not write a single line in the code behind, we need to do something from the XAML which will cause the storyboard to run.

We can achieve this functionality be using the Microsoft.Expression.Interactions and System.Windows.Interactivity DLL assemblies. They provides interfaces to call a storyboard on some event. To do this, we need to add the assembly references of those dlls. Add them from the "Add Reference" dialog as shown below:

Loader Demo - Adding External Libraries (Microsoft.Expression.Interactions and System.Windows.Interactivity)

Once you added the assembly references, we will add the following xmlns namespaces in the XAML file. Those two namespace will help us to call the storyboard easily from the XAML without writing any code behind file.

Loader Demo - Adding xmlns Namespaces in the XAML

Just after the resource declaration, add the below code:

XML
<i:Interaction.Triggers>
   <i:EventTrigger EventName="Loaded">
        <ei:ControlStoryboardAction Storyboard="{StaticResource LoaderAnimation}"/>
   </i:EventTrigger>
</i:Interaction.Triggers>

This will run the storyboard from the loaded event. That means, once the usercontrol has been loaded in the UI, it will call the Storyboard to start executing the animation.

See It In Action

Upto this, our code is ready. Now, add the said CurcularLoader.xaml UserControl in the MainPage.xaml file. We will place it inside the LayoutRoot. Make sure to set a Foreground color for the circles. Build the solution and check if there are any errors. If so, fix them and run the project. You will see the following UI inside the browser window:

Loader Demo - Showing Demo of the Loader Control

If you resize the browser, it will change the size of the circular loader in proportion to the parent panel. Now we will do a little change here. While adding the user control in the main page, we will specify its height and width. For our example, we will use 50 x 50 as the dimension of the loader control.

Find the complete source code of the MainPage.xaml where we added the loader control:

XML
<UserControl x:Class="LoaderDemo.MainPage"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:LoaderDemo="clr-namespace:LoaderDemo">
    <Grid>
       <LoaderDemo:CircularLoader Foreground="Black" 
                                   HorizontalAlignment="Center" 
                                  VerticalAlignment="Center"
                                   Height="50" Width="50"/>
   </Grid>
</UserControl>

Now once you run the application again, you will see the following UI where the loader control has a fixed size:

Loader Demo - Showing Demo of the Loader Control after Resize

In this case, if you resize the browser, it will not change its size because now, it has a proper dimension. Hope you enjoyed reading the article. This helped you to understand the same in depth. Now you will be able to modify the same code and implement additional behavior. You can also expose some APIs on a need basis.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)