使用WPF和MVVM模式实现进度条(使用BackgroundWorker)

时间:2011-10-06 21:03:13

标签: wpf mvvm progress-bar backgroundworker

注意:此代码现在可以使用。我修正了一些愚蠢的错误,我还修改了代码,正如Steve Greatrex指出的那样。

原始发布链接How to implement a progress bar using the MVVM pattern

ProgressbarSampleView.xaml

  <UserControl x:Class="MyProject.ProgressbarSampleView"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
               Height="718" Width="1024">

  <ProgressBar Grid.Row="1" 
                 Value="{Binding CurrentProgress, Mode=OneWay}" 
                 Visibility="{Binding ProgressVisibility}" 
                 Margin="22,0,25,0" />

  <Button   Grid.Row="2"
            Content="Start Now"  
            Height="30" 
            Width="80" 
            HorizontalAlignment="Left" 
            Margin="22,4,0,0" 
            Name="btnStartNow" 
            VerticalAlignment="Top" 
            Command="{Binding Path=InstigateWorkCommand}" 
            />
  </UserControl>

ProggressbarSampleViewModel.cs

  namespace MyProject
  {
   public class ProggressbarSampleViewModel: ViewModelBase
   {
     private readonly BackgroundWorker worker; 
     private readonly ICommand instigateWorkCommand;

     public ProggressbarSampleViewModel()
     {
        this.instigateWorkCommand = new 
                      RelayCommand(o => this.worker.RunWorkerAsync(), o => !this.worker.IsBusy);
        this.worker = new BackgroundWorker();
        this.worker.DoWork += this.DoWork;
        this.worker.ProgressChanged += this.ProgressChanged;
    }


    public ICommand InstigateWorkCommand
    {
        get { return this.instigateWorkCommand; }
    }

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

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

    private void DoWork(object sender, DoWorkEventArgs e)
    {
        // do time-consuming work here, calling ReportProgress as and when you can   
        for (int i = 0; i < 100; i++)
        {
            Thread.Sleep(1000);
            _currentProgress = i;
            OnPropertyChanged("CurrentProgress");
        }
    }

  }

1 个答案:

答案 0 :(得分:1)

StartNowCommand永远不会调用BackgroundWorker - 它只是在UI线程上同步执行DoStartNow方法。基于此,我猜想当你点击链接到StartNow命令的按钮时,你会看到你的用户界面冻结......?

您应该将按钮绑定到实际以异步方式运行InstigateWorkCommand代码的BackgroundWorker

在此实现中,我认为您根本不需要StartNowCommand。我也没有在视图模型中的任何位置看到DoWork事件处理程序,所以我假设它只是调用DoStartNow

相关问题