如何使用MVVM模式实现进度条

jpg*_*ner 35 c# wpf mvvm

我有一个基于MVVM设计模式的WPF应用程序.

我希望在应用程序中实现一个遵循MVVM模式的进度条.

有没有人对如何实现这一点有任何建议?

提前致谢

Ken*_*art 59

通常,您的UI只会绑定到VM中的属性:

<ProgressBar Value="{Binding CurrentProgress, Mode=OneWay}" 
             Visibility="{Binding ProgressVisibility}"/>
Run Code Online (Sandbox Code Playgroud)

您的VM将使用a 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,非常有用的例子!我在测试期间发现的两件事值得注意:1)"CurrentProgress"的setter必须是公共的,或者必须在Progressbar上明确指定`OneWay`模式绑定.默认值似乎是TwoWay(对于Progressbar来说很奇怪),因此绑定引擎会引发私有setter的异常.2)当使用`ReportProgress`时,似乎有必要将`BackgroundWorker`的`WorkerReportsProgress`属性设置为`true`.否则,线程执行会以静默方式停止(没有异常,仅在`RunWorkerCompleted`事件args中可见). (3认同)
  • @Kent Boogaart写完这样的字符串后:"this.instigateWorkCommand = new DelegateCommand(o => this.worker.RunWorkerAsync,o =>!this.worker.IsBusy);" .VS2010抛出错误:"委托'system.action'不接受1个参数".你能说出如何克服它吗? (2认同)

Tho*_*que 10

使用ProgressBar控件并将其Value属性绑定到ViewModel的属性:

视图

<ProgressBar Minimum="0" Maximum="0" Value="{Binding CurrentProgress}" />
Run Code Online (Sandbox Code Playgroud)

视图模型

private double _currentProgress;
public double CurrentProgress
{
    get { return _currentProgress; }
    private set
    {
        _currentProgress = value;
        OnPropertyChanged("CurrentProgress");
    }
}
Run Code Online (Sandbox Code Playgroud)


HCL*_*HCL 6

向VM添加两个属性:

bool IsProgressBarVisible
double ProgressValue
Run Code Online (Sandbox Code Playgroud)

如果在VM中启动长时间操作,请将IsProgressBarVisible属性设置为true,并将ProgressValue周期设置为当前进度值.尝试计算0到100之间的值.这样做的好处是您不必提供最小值和最大值.异步操作完成后,将IsProgressBarVisible设置为false.

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

<ProgressBar Value="{Binding ProgressValue}" Visibility="{Binding IsProgressBarVisible,Converter={StaticResource BooleanToVisibility_ValueConverter}}"/> 
Run Code Online (Sandbox Code Playgroud)