23

I'm using progress bar of WPF (C#) to describe the process's progress.

My algorithm is below:

DoSomethingCode1();
ProgressBar.SetPercent(10); // 10%
DoSomethingCode2();
ProgressBar.SetPercent(20); // 20%

...

DoSomethingCode10();
ProgressBar.SetPercent(100); // 100%

It's ok, but it will make the progress bar was not sequent.

Someone can tell me some suggestions that make the progress bar is updated softly?

TTGroup
  • 3,575
  • 10
  • 47
  • 79
  • 8
    Do not manipulate UIElements in code. Learn MVVM. Use a background thread to perform your operations and then dispatch the update of the percentage property to the UI Thread. – Federico Berasategui Jan 23 '13 at 17:36
  • 1
    [This Answer](http://stackoverflow.com/questions/5774473/using-backgroundworker-with-progressbar-in-wpf) might help you out. – Abdusalam Ben Haj Jan 23 '13 at 18:06
  • 1
    What does "not sequent" mean? What is "soft updating"? – Patrick Jan 23 '13 at 18:18
  • 1
    @HighCore, Abzy: Thank you, but it is not my problem, The above code is Pseudocode. – TTGroup Jan 24 '13 at 05:46
  • @Patrick: I don't know which words can describe them exactly! But from above code, you can see the progress bar will update to 10% -> 20% -> ... -> 100%, it look not smooth. – TTGroup Jan 24 '13 at 05:50
  • @Patrick - TTGroup wants it to, instead of jumping directly to 100 from 10, to update by gliding to 100%. – Cullub Aug 22 '14 at 12:27
  • 3
    Thank you, I have been waiting in this thread for more than 1.5 years wondering that. – Patrick Aug 22 '14 at 14:31

4 Answers4

43

You can use a behavior!

public class ProgressBarSmoother
{
    public static double GetSmoothValue(DependencyObject obj)
    {
        return (double)obj.GetValue(SmoothValueProperty);
    }

    public static void SetSmoothValue(DependencyObject obj, double value)
    {
        obj.SetValue(SmoothValueProperty, value);
    }

    public static readonly DependencyProperty SmoothValueProperty =
        DependencyProperty.RegisterAttached("SmoothValue", typeof(double), typeof(ProgressBarSmoother), new PropertyMetadata(0.0, changing));

    private static void changing(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var anim = new DoubleAnimation((double)e.OldValue, (double)e.NewValue, new TimeSpan(0,0,0,0,250));
        (d as ProgressBar).BeginAnimation(ProgressBar.ValueProperty, anim, HandoffBehavior.Compose);
    }
}

Your XAML would look like this:

<ProgressBar local:ProgressBarSmoother.SmoothValue="{Binding Progress}">

Whenever the Progress property you are binding to in the xaml changes, the code in the ProgressBarSmoother behavior will run, adding the animation to the progress bar for you with the appropriate values for To and From!

Owen Johnson
  • 2,416
  • 2
  • 19
  • 23
  • 8
    I added this solution because it allows you to decouple whatever is reporting progress and the view that contains the progress bar. – Owen Johnson Jan 06 '14 at 19:47
  • Love this. Adjusted the duration a little bit, works like a charm. However, since the standard progress bar in Windows since Vista does this, it should have already been in the WPF progress bar... – OregonGhost Dec 18 '14 at 12:00
  • was a perfect drop in solution for my little client. This rocks, thanks! – Master Azazel Feb 05 '20 at 17:28
22

You could call the BeginAnimation method to animate the ProgressBar's Value property. In my example below, I used a DoubleAnimation.

I created an extension method that takes in the desired percentage:

public static class ProgressBarExtensions
{
    private static TimeSpan duration = TimeSpan.FromSeconds(2);

    public static void SetPercent(this ProgressBar progressBar, double percentage)
    {
        DoubleAnimation animation = new DoubleAnimation(percentage, duration);
        progressBar.BeginAnimation(ProgressBar.ValueProperty, animation);          
    }
}

So in your code you could simply call:

myProgressBar.SetPercent(50);

Doing this simply smooths out the transition so it looks nicer. To quote another answer: "The idea is that a progress bar reports actual progress - not time elapsed. It's not intended to be an animation that just indicates something is happening." However, the default style of the progress bar does have a pulsating effect which can imply work is happening.

Community
  • 1
  • 1
Matthew Steven Monkan
  • 8,170
  • 4
  • 53
  • 71
  • @Matt nice. What are your references? the things you put after "using"? Thanks! – Cullub Aug 22 '14 at 12:33
  • 2
    Sorry - After a little research - add presentationcore.dll to references, then "using System.Windows.Media". See [This Microsoft Website](http://msdn.microsoft.com/en-us/library/system.windows.media.animation.doubleanimation%28v=vs.110%29.aspx) – Cullub Aug 22 '14 at 12:46
  • What .NET version is this? There is no BeginAnimation event on the ProgressBar? – cullimorer Jul 30 '17 at 11:12
3

Check if you can modify the style of the progressbar and set an Easing function to it's storyboard that modifies the "filling" of the progressbar and by doing that it will have a smooth transition.

dutzu
  • 3,883
  • 13
  • 19
-1

try this out.

private void updateProgressBar(int percent)
    {
        if (ProgressBar.InvokeRequired)
        {
            updateProgressBarCallback cb = new updateProgressBarCallback(updateProgressBar);
            this.Invoke(cb, new object[] { percent });
        }
        else
        {
            ProgressBar.Value = percent;
            ProgressBar.Update();
            ProgressBar.Refresh();
            ProgressBar.Invalidate();
        }
kleopatra
  • 51,061
  • 28
  • 99
  • 211
Arun
  • 1
  • 5
  • Sorry not working for me. I copied and pasted your code snippet. The errors saying the following : System.Windows.Control.ProgressBar does not contain definition for Update,Refresh,Invalidate. The namespace name updateProgressBarCallback could not be found, are you missing a using directive or an assembly reference? – Arun Oct 08 '13 at 04:36
  • if you did this, you would need something like: delegate void updateProgressBarCallback(int percent); added to the code. – SedJ601 Aug 18 '16 at 13:52
  • If your UI thread is busy, these draw calls will go into the event queue and happen all at once. The progress bar won't animate. – Owen Johnson Feb 01 '18 at 21:20