2010-08-19 154 views
31

我有一个基于MVVM设计模式构建的WPF应用程序。如何使用MVVM模式实现进度条

我希望在应用中实现一个进度条,它遵循MVVM模式。

有没有人有任何建议如何实现这个?

在此先感谢

回答

52

通常你的UI只会绑定属性在你的虚拟机:

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

你的虚拟机将使用一个BackgroundWorker做在后台线程的工作,并定期更新值为CurrentProgress。事情是这样的:

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; 
    } 
} 
+0

嗨肯特,我需要一个单独的模型和视图模型的进度条?或者我会添加一个进度条到每个现有的视图,我打算使用它? – jpgooner 2010-08-19 09:43:29

+0

我会从每个视图使用一个视图开始,然后决定是否可以将视图抽象为可重用组件。 – 2010-08-19 09:44:36

+0

是的好呼喊,谢谢你的回答everone – jpgooner 2010-08-19 09:46:38

8

使用ProgressBar控制及其Value属性绑定到视图模型的属性:

查看

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

视图模型

private double _currentProgress; 
public double CurrentProgress 
{ 
    get { return _currentProgress; } 
    private set 
    { 
     _currentProgress = value; 
     OnPropertyChanged("CurrentProgress"); 
    } 
} 
+0

如何将此命令与我的命令连接?也就是说,我有一个按钮,点击后,我想启动进度条,直到完成操作。 – 2014-07-28 15:02:55

+0

@KalaJ,你只需要在你的动作中更新CurrentProgress属性(例如,如果它是一个循环,每次迭代更新值) – 2014-07-28 15:34:29

+0

事情是我只是等待系统读取/检测CD,当我插入光盘放入我的电脑。有时,系统需要一段时间才能读取CD,而其他时间则不需要。我如何更新这样的值?我想也许使用一个不确定的进度条,但我仍然困惑如何将它连接到我的命令? – 2014-07-28 17:25:09

6

添加两个属性到您的VM:

bool IsProgressBarVisible 
double ProgressValue 

如果您在VM开始很长一段时间的操作,设置IsProgressBarVisible属性为true,并设置ProgressValue定期到当前的进度值。尝试计算一个介于0和100之间的值。这具有您不必提供最小值和最大值的优点。 异步操作完成后,将IsProgressBarVisible设置为false。

在XAML中,绑定到这两个属性。使用值转换器将布尔可见性转换为可见性。

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