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

3

注意:此代码现在可用。我已经修正了一些愚蠢的错误,并按照Steve Greatrex指出的进行了修订。

原始发布链接:如何使用MVVM模式实现进度条

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
在编写以下字符串后:"this.instigateWorkCommand = new RelayCommand(o => this.worker.RunWorkerAsync, o => !this.worker.IsBusy);",VS2010会抛出错误:"delegate 'system.action' does not take 1 arguments"。你能告诉我如何解决这个问题吗?你使用的是哪个版本的.Net Framework? - StepUp
1个回答

1

StartNowCommand 从不调用BackgroundWorker - 它只是在UI线程上同步执行DoStartNow方法。基于此,我猜测当你点击与StartNow命令相关联的按钮时,你会看到UI冻结了吗?

你应该将按钮绑定到实际异步运行BackgroundWorker代码的InstigateWorkCommand

在这个实现中,我认为你根本不需要StartNowCommand。我也没有在你的视图模型中找到DoWork事件处理程序,所以我假设它只是调用DoStartNow


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接