none
Spinning Progress Control in WPF

    Question

  • How can I develop a spinning progress control as is displayed while executing a query in the SQL Server 2005? I first thought of using the Image in a using control and applying animation to it. But it's not working. Any ideas/pointers??

     

    Friday, January 04, 2008 9:45 PM

Answers

  • Here is one that I cooked up.  I'm sure the pros will come up with something that is 100% XAML though.

     

    <Window x:Class="RotatingDial.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300" Visibility="Visible">
        <Grid>
            <Button Height="23" HorizontalAlignment="Left" Margin="30,24,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click">Start</Button>
            <Button Height="23" HorizontalAlignment="Right" Margin="0,24,62,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click">Stop</Button>
            <Canvas x:Name="canvas2" Height="100" Width="100" Visibility="Collapsed">
                <Canvas Height="100" Width="100" x:Name="canvas1" RenderTransformOrigin=".5,.5">
                    <Canvas.RenderTransform>
                        <RotateTransform x:Name="spin" Angle="0"/>
                    </Canvas.RenderTransform>                
                </Canvas>
                <Label Height="23" Canvas.Left="26" Canvas.Top="36" Width="48">Loading</Label>
            </Canvas>
        </Grid>
    </Window>

     

    //Show spinner
    private void button1_Click(object sender, RoutedEventArgs e)
    {
        drawCanvas();
        canvas2.Visibility = Visibility.Visible;
        DoubleAnimation a = new DoubleAnimation();
        a.From = 0;
        a.To = 360;
        a.RepeatBehavior = RepeatBehavior.Forever;
        a.SpeedRatio = 1;
     
        spin.BeginAnimation(RotateTransform.AngleProperty, a);
    }
     
    //Hide spinner
    private void button2_Click(object sender, RoutedEventArgs e)
    {
        canvas2.Visibility = Visibility.Collapsed;
    }
     
    //Spinner draw
    void drawCanvas()
    {
        for (int i = 0; i < 12; i++)
        {
            Line line = new Line() { X1 = 50, X2 = 50, Y1 = 0, Y2 = 20,
                StrokeThickness = 5, Stroke = Brushes.Gray, Width=100, Height=100};
            line.VerticalAlignment = VerticalAlignment.Center;
            line.HorizontalAlignment = HorizontalAlignment.Center;
            line.RenderTransformOrigin = new Point(.5, .5);
            line.RenderTransform = new RotateTransform(i*30);
            line.Opacity = (double)i / 12;
     
            canvas1.Children.Add(line);
     
        }
    }
    Friday, January 04, 2008 11:36 PM

All replies

  • Here is one that I cooked up.  I'm sure the pros will come up with something that is 100% XAML though.

     

    <Window x:Class="RotatingDial.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300" Visibility="Visible">
        <Grid>
            <Button Height="23" HorizontalAlignment="Left" Margin="30,24,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click">Start</Button>
            <Button Height="23" HorizontalAlignment="Right" Margin="0,24,62,0" Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click">Stop</Button>
            <Canvas x:Name="canvas2" Height="100" Width="100" Visibility="Collapsed">
                <Canvas Height="100" Width="100" x:Name="canvas1" RenderTransformOrigin=".5,.5">
                    <Canvas.RenderTransform>
                        <RotateTransform x:Name="spin" Angle="0"/>
                    </Canvas.RenderTransform>                
                </Canvas>
                <Label Height="23" Canvas.Left="26" Canvas.Top="36" Width="48">Loading</Label>
            </Canvas>
        </Grid>
    </Window>

     

    //Show spinner
    private void button1_Click(object sender, RoutedEventArgs e)
    {
        drawCanvas();
        canvas2.Visibility = Visibility.Visible;
        DoubleAnimation a = new DoubleAnimation();
        a.From = 0;
        a.To = 360;
        a.RepeatBehavior = RepeatBehavior.Forever;
        a.SpeedRatio = 1;
     
        spin.BeginAnimation(RotateTransform.AngleProperty, a);
    }
     
    //Hide spinner
    private void button2_Click(object sender, RoutedEventArgs e)
    {
        canvas2.Visibility = Visibility.Collapsed;
    }
     
    //Spinner draw
    void drawCanvas()
    {
        for (int i = 0; i < 12; i++)
        {
            Line line = new Line() { X1 = 50, X2 = 50, Y1 = 0, Y2 = 20,
                StrokeThickness = 5, Stroke = Brushes.Gray, Width=100, Height=100};
            line.VerticalAlignment = VerticalAlignment.Center;
            line.HorizontalAlignment = HorizontalAlignment.Center;
            line.RenderTransformOrigin = new Point(.5, .5);
            line.RenderTransform = new RotateTransform(i*30);
            line.Opacity = (double)i / 12;
     
            canvas1.Children.Add(line);
     
        }
    }
    Friday, January 04, 2008 11:36 PM
  •  

    Thanks!! jbroddie. It worked..
    Tuesday, January 15, 2008 10:35 PM
  • Hey, thanks for posting that! I was able to adapt it for use in Silverlight...

    XAML

    1 <UserControl x:Class="SilverlightSpinner.Page" 
    2     xmlns="http://schemas.microsoft.com/client/2007"  
    3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    4     Width="300" Height="300"
    5     <Grid x:Name="LayoutRoot" Background="White"
    6         <Button Height="23" HorizontalAlignment="Left" Margin="30,24,0,0" x:Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" Content="Start"/> 
    7         <Button Height="23" HorizontalAlignment="Right" Margin="0,24,0,0" x:Name="button2" VerticalAlignment="Top" Width="75" Click="button2_Click" Content="Stop"/> 
    8         <Canvas x:Name="canvas2" Height="100" Width="100" Visibility="Collapsed"
    9             <Canvas Height="100" Width="100" x:Name="canvas1" RenderTransformOrigin=".5,.5"
    10                 <Canvas.Resources> 
    11                     <Storyboard x:Name="spinningAnimation"
    12                         <DoubleAnimation From="0" To="360" RepeatBehavior="Forever" SpeedRatio="0.75" 
    13                                          Storyboard.TargetName="spin" Storyboard.TargetProperty="(FrameworkElement.Angle)"/> 
    14                     </Storyboard> 
    15                 </Canvas.Resources> 
    16                 <Canvas.RenderTransform> 
    17                     <RotateTransform x:Name="spin" Angle="0"/> 
    18                 </Canvas.RenderTransform> 
    19             </Canvas> 
    20             <TextBlock Height="23" Canvas.Left="26" Canvas.Top="36" Width="Auto" Text="Loading" /> 
    21         </Canvas> 
    22     </Grid> 
    23 </UserControl> 
    24  

    C#

    1 using System.Windows; 
    2 using System.Windows.Controls; 
    3 using System.Windows.Media; 
    4 using System.Windows.Shapes; 
    5  
    6 namespace SilverlightSpinner 
    7
    8     public partial class Page : UserControl 
    9     { 
    10         public Page() 
    11         { 
    12             InitializeComponent(); 
    13         } 
    14  
    15         private void button1_Click(object sender, RoutedEventArgs e) 
    16         { 
    17             drawCanvas(); 
    18  
    19             canvas2.Visibility = Visibility.Visible; 
    20  
    21             spinningAnimation.Begin(); 
    22         } 
    23  
    24         private void button2_Click(object sender, RoutedEventArgs e) 
    25         { 
    26             spinningAnimation.Stop(); 
    27  
    28             canvas2.Visibility = Visibility.Collapsed; 
    29         } 
    30  
    31         void drawCanvas() 
    32         { 
    33             for (int i = 0; i < 12; i++) 
    34             { 
    35                 Line line = new Line() 
    36                 { 
    37                     X1 = 50, 
    38                     X2 = 50, 
    39                     Y1 = 0, 
    40                     Y2 = 20, 
    41                     StrokeThickness = 5, 
    42                     Stroke = new SolidColorBrush(Color.FromArgb(255, 225, 225, 225)), 
    43                     Width = 100, 
    44                     Height = 100, 
    45                     VerticalAlignment = VerticalAlignment.Center, 
    46                     HorizontalAlignment = HorizontalAlignment.Center, 
    47                     RenderTransformOrigin = new Point(.5, .5), 
    48                     RenderTransform = new RotateTransform() { Angle = i * 30 }, 
    49                     Opacity = (double)i / 12 
    50                 }; 
    51  
    52                 canvas1.Children.Add(line); 
    53             } 
    54         } 
    55     } 
    56
    57  
    Tuesday, June 17, 2008 6:41 PM
  • Here is a simple spinning/throbbing progress control in Xaml.  Put it in a canvas and use a ScaleTransform to adjust the size as needed.

    <Window x:Class="TestProject.TestWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="TestWindow" Height="475.857" Width="521.585"
        <Grid> 
            <Canvas Name="sample"
                <Canvas Name="spinningProgress" Margin="0,0,0,0" Height="130" Width="130"  VerticalAlignment="Top" HorizontalAlignment="Left"
                    <Canvas Name="innerCanvas" Height="110" Width="110"  VerticalAlignment="Center" HorizontalAlignment="Center" Canvas.Left="10" Canvas.Top="10"
                        <Ellipse Margin="45,-5,0,0" Name="ellipseLarge" Stroke="Blue" Height="20" Width="20" VerticalAlignment="Top" Fill="Blue" HorizontalAlignment="Left" /> 
                        <Ellipse Margin="85.3553,14.6447,0,0" Name="ellipse2" Stroke="Blue" HorizontalAlignment="Left" Width="10" Height="10" VerticalAlignment="Top" Fill="Blue" /> 
                        <Ellipse Margin="100,50,0,0" Name="ellipse3" Stroke="Blue" Fill="Blue" HorizontalAlignment="Left" Height="10" Width="10" VerticalAlignment="Top" /> 
                        <Ellipse Margin="85.3553,85.3553,0,0" Name="ellipse4" Stroke="Blue" HorizontalAlignment="Left" Width="10" Height="10" VerticalAlignment="Top" Fill="Blue" /> 
                        <Ellipse Margin="50,100,0,0" Name="ellipse5" Stroke="Blue" Fill="Blue" HorizontalAlignment="Left" Width="10" Height="10" VerticalAlignment="Top" /> 
                        <Ellipse Margin="14.6447,85.3553,0,0" Name="ellipse6" Stroke="Blue" HorizontalAlignment="Left" Width="10" Height="10" VerticalAlignment="Top" Fill="Blue" /> 
                        <Ellipse Margin="0,50,0,0" Name="ellipse7" Stroke="Blue" HorizontalAlignment="Left" Width="10" Fill="Blue" Height="10" VerticalAlignment="Top" /> 
                        <Ellipse Margin="12.1447,12.1447,0,0" Name="ellipseMedium" Width="15" Height="15" Stroke="Blue" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="Blue" /> 
                    </Canvas> 
                    <Canvas.RenderTransform> 
                        <RotateTransform x:Name="spin" Angle="0" CenterX="65" CenterY="65"/> 
                    </Canvas.RenderTransform> 
                    <Canvas.Triggers> 
                        <EventTrigger RoutedEvent="Canvas.Loaded"
                            <BeginStoryboard> 
                                <Storyboard> 
                                    <DoubleAnimationUsingKeyFrames 
                                    Storyboard.TargetName="spinningProgress"  
                                    Storyboard.TargetProperty="(Canvas.RenderTransform).(RotateTransform.Angle)" 
                                    RepeatBehavior="Forever" Duration="0:0:1"
                                        <DiscreteDoubleKeyFrame Value="45" KeyTime="0:0:0.125" /> 
                                        <DiscreteDoubleKeyFrame Value="90" KeyTime="0:0:0.25" /> 
                                        <DiscreteDoubleKeyFrame Value="135" KeyTime="0:0:0.375" /> 
                                        <DiscreteDoubleKeyFrame Value="180" KeyTime="0:0:0.5" /> 
                                        <DiscreteDoubleKeyFrame Value="225" KeyTime="0:0:0.675" /> 
                                        <DiscreteDoubleKeyFrame Value="270" KeyTime="0:0:0.75" /> 
                                        <DiscreteDoubleKeyFrame Value="315" KeyTime="0:0:0.875" /> 
                                    </DoubleAnimationUsingKeyFrames> 
                                </Storyboard> 
                            </BeginStoryboard> 
                        </EventTrigger> 
                    </Canvas.Triggers> 
                </Canvas> 
                <Canvas.RenderTransform> 
                    <ScaleTransform ScaleX="0.8" ScaleY="0.8"/> 
                </Canvas.RenderTransform> 
            </Canvas> 
        </Grid> 
    </Window> 
     

    Friday, December 05, 2008 1:07 AM
  • Hello it's really fun what uve done but i don't know in vb.net how to display it during a loading time

     

    for example, i have a method (or an event) that take a long time (like a button click with a lot of action) how to display the animation during this time please

     

    thanks all for your work

    Tuesday, June 08, 2010 6:12 PM
  • I see it's been a while since anybody replied but i'll reply anyways :)

    What i do when i execute methods that take some time and i want to display some "busy" behaviour and also not kill my UI, i use BackgroundWorker.

    BackgroundWorker places code execution in a separate thread and executes it Async.

    See example below:

     //Execute query async
                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += delegate(object s, DoWorkEventArgs args)
                {
                    args.Result = DB.DBUtils.RunSqlQuery(this.QueryText, Connection);
                };
                worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
                {
                    //Stop animation here
                    this.Data = args.Result as DataTable;
                    this.BindData();
                };
                worker.RunWorkerAsync();
                //Start animation here

    So pretty much after you start the worker job (worker.RunWorkerAsync) you can start your animation.

    As seen above, in the RunWorkerCompleted event, you stop the animation.

    All the code will run nice and smooth in the background and you don't have to care about anything else anymore.

    Hope it helps. 

    Sunday, March 20, 2011 1:36 PM
  • hi

    the script worked for me when in used it as seperate project

    when tried to implement in the runnig project its spinning only after the next window opens

    Saturday, November 09, 2013 7:38 AM