简体   繁体   中英

How to implement a progress bar using the MVVM pattern

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

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

<ProgressBar Value="{Binding CurrentProgress, Mode=OneWay}" 
             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;
    }
}

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");
    }
}

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}}"/> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM