tags:

views:

141

answers:

3

I have a WPF application which is built on the MVVM design pattern.

I wish to implement a progress bar in the app, that follows the MVVM pattern.

Does any one have any suggestions on how to implement this?

Thanks in advance

+4  A: 

Typically your UI would simply bind to properties in your VM:

<ProgressBar Value="{Binding CurrentProgress}" Visibility="{Binding ProgressVisibility}"/>

Your VM would use a BackgroundWorker to do the work on a background thread, and to periodically update the CurrentProgress value. Something like this:

public class MyViewModel : ViewModel
{
    private readonly BackgroundWorker worker;
    private readonly ICommand instigateWorkCommand;
    private int currentProgress;

    public MyViewModel()
    {
        this.instigateWorkCommand = new DelegateCommand(o => this.worker.RunWorkerAsync, o => !this.worker.IsBusy);

        this.worker = new BackgroundWorker();
        this.worker.DoWork += this.DoWork;
        this.worker.ProgressChanged += this.ProgressChanged;
    }

    // your UI binds to this command in order to kick off the work
    public ICommand InstigateWorkCommand
    {
        get { return this.instigateWorkCommand; }
    }

    public int CurrentProgress
    {
        get { return this.currentProgress; }
        private set
        {
            if (this.currentProgress != value)
            {
                this.currentProgress = value;
                this.OnPropertyChanged(() => this.CurrentProgress);
            }
        }
    }

    private void DoWork(object sender, DoWorkEventArgs e)
    {
        // do time-consuming work here, calling ReportProgress as and when you can
    }

    private void ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        this.CurrentProgress = e.ProgressPercentage;
    }
}

HTH,
Kent

Kent Boogaart
Hi Kent, would I need a seperate model and view model for the progress bar? or would I add a progress bar to each existing view where i intent to use it?
jpgooner
I would start simple by using one per view and then decide whether you can abstract that into a reusable component.
Kent Boogaart
Yep good shout, thanks for your answers everone
jpgooner
+3  A: 

Use a ProgressBar control and bind its Value property to a property of the ViewModel:

View

<ProgressBar Minimum="0" Maximum="0" Value="{Binding CurrentProgress}" />

ViewModel

private double _currentProgress;
public double CurrentProgress
{
    get { return _currentProgress; }
    private set
    {
        _currentProgress = value;
        OnPropertyChanged("CurrentProgress");
    }
}
Thomas Levesque
+1  A: 

Add two properties to your VM:

bool IsProgressBarVisible
double ProgressValue

If you start a long time operation in your VM, set the IsProgressBarVisible-property to true and set the ProgressValue periodical to the current progress value. Try to calculate a value between 0 and 100. This has the advantage that you don't have to provide a minimum and maximum value. After the asynchronous operation has completed, set the IsProgressBarVisible to false.

In XAML, bind to these two properties. Use a value converter to convert the boolean visibility to a Visibility.

<ProgressBar Value="{Binding ProgressValue}" Visibility="{Binding IsProgressBarVisible,Converter={StaticResource BooleanToVisibility_ValueConverter}}"/> 
HCL