在 WPF C# MVVM 中使用进度条 [英] Using progress bar in WPF C# MVVM

查看:130
本文介绍了在 WPF C# MVVM 中使用进度条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是在另一组脚本(计算)运行时更新进度条.

我遵循了

这是进度条脚本

在下面的脚本中,我将 progressBarCounternoOfData 作为另一个脚本中的值包含在方法中.

证明数据已更新

公共部分类 ProgressBarTaskOnWorkerThread : Window{公共 ProgressBarTaskOnWorkerThread(){初始化组件();}私有无效Window_ContentRendered(对象发送者,EventArgs e){BackgroundWorker worker = new BackgroundWorker();worker.WorkerReportsProgress = true;worker.DoWork += worker_DoWork;worker.ProgressChanged += worker_ProgressChanged;worker.RunWorkerAsync();}void worker_DoWork(对象发送者,DoWorkEventArgs e){EtabsDataFormatting.ViewModel.SpliceViewModel data = new EtabsDataFormatting.ViewModel.SpliceViewModel();for (int i = data.progressBarCounter; i 

这是我的 XAML 代码的一部分,用于开始计算和运行进度条的按钮

命令 Binding = RunCalcBtn 绑定到计算脚本,因此,我创建了一个点击来运行进度条.

Progressbar XAML.cs 按钮点击

此部分显示进度条,但不更新.

private void PrgBar_Click(object sender, RoutedEventArgs e){ProgressBar.ProgressBarTaskOnWorkerThread progressWindow = new ProgressBar.ProgressBarTaskOnWorkerThread();progressWindow.Show();}

非常感谢您提前帮助我!

解决方案

正如 Flithor 所说,实现这一目标的最佳方法是使用 Progress.

我简要说明了如何使用它.

首先,您需要在您的视图模型中创建一个 Property,以便您可以将 ProgressBar 的值绑定到某些东西.您的 ViewModel 需要实现 INotifyPropertyChanged,以便属性 set 可以调用 RaisePropertyChangedEvent.

接下来在按钮单击调用的方法中创建一个 Progress 并将其传递给您的工作方法.为此使用 ICommand,以便它可以绑定到您的 Button(您不需要 Click 事件).像这样:

var progress = new Progress(percent =>{ProgressProperty = 百分比;});await Task.Run(() => myWorker(progress));

最后在您的工作方法中,您定期更新值,如下所示:

private void myWorker(IProgress progress){进度.报告(1);//...进度报告(100);}

顺便解释一下:我使用的是整数,但如果您想要非常精细的计算,也可以使用双精度数!Progress 对象的构造函数采用 ProgressProperty(我给绑定到 ProgressBar 的属性的名称)作为参数.这意味着当工作人员调用 Report() 时,ProgressProperty 会自动更新为新值,因此可以反映在 UI 中.最后使用 await 调用您的工作方法,以便 UI 能够根据每个递增的值进行更新.

有关 Progress 的完整说明,请参阅 Stephen Cleary 的 博客

My goal is to update the progress bar while another set of script (calculations) is running.

I have followed the sample files from here and tried to bind it to my MVVM script but the progress bar would not update.

Here is the Progressbar script

In the script below, I have included progressBarCounter and noOfDataas a value in another script that is calculated in a method.

Proof that data is updated

public partial class ProgressBarTaskOnWorkerThread : Window
{
    public ProgressBarTaskOnWorkerThread()
    {
        InitializeComponent();
    }

    private void Window_ContentRendered(object sender, EventArgs e)
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.WorkerReportsProgress = true;
        worker.DoWork += worker_DoWork;
        worker.ProgressChanged += worker_ProgressChanged;

        worker.RunWorkerAsync();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        EtabsDataFormatting.ViewModel.SpliceViewModel data = new EtabsDataFormatting.ViewModel.SpliceViewModel();

        for (int i = data.progressBarCounter; i < data.noOfData;)
        {
            (sender as BackgroundWorker).ReportProgress(i);
        }
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        pbStatus.Value = e.ProgressPercentage;
        int perc = Convert.ToInt32(pbStatus.Value);
        UpdateProgress(perc);
    }

    public void UpdateProgress(int percentage)
    {
        pbStatus.Value = percentage;
        if (percentage == 100)
        {
            Close();
        }
    }
}

Here is part of my XAML code for the button to start calculations and run the progressbar

The command Binding = RunCalcBtn is bound to the calculation scripts, therefore, I have created a click to run the progress bar instead.

<Button x:Name = "ApplyButton" Margin="0 1 0 1" Content ="Start Calculation" Command="{Binding RunCalcBtn, Mode=TwoWay}" Click ="PrgBar_Click"/>

Progressbar XAML.cs button click

This part displays the progress bar, but it does not update.

private void PrgBar_Click(object sender, RoutedEventArgs e)
{
    ProgressBar.ProgressBarTaskOnWorkerThread progressWindow = new ProgressBar.ProgressBarTaskOnWorkerThread();
    progressWindow.Show();
}

Thank you so much for helping me in advance!

解决方案

As Flithor has said, the best way to achieve this is with Progress<T>.

I give a short illustration of how to use this.

Firstly you need to create a Property in your View Model so that you can bind the ProgressBar's Value to something. Your ViewModel will need to implement INotifyPropertyChanged so that the Property set can invoke RaisePropertyChangedEvent.

Next create a Progress inside the method called by the Button click and pass it to your worker method. Use an ICommand for this, so that it can be bound to your Button (you don't need the Click event). Something like this:

var progress = new Progress<int>(percent =>
    {
        ProgressProperty = percent;
    });

await Task.Run(() => myWorker(progress));

Finally within your worker method you periodically update the value like this:

private void myWorker(IProgress<int> progress)
{
    progress.Report(1);
    // ...
    progress.Report(100);
}

By way of explanation: I used an integer, but you can also use a double if you want really fine calculations! The constructor of the Progress object takes the ProgressProperty (the name I gave to the property that gets bound to the ProgressBar) as a parameter. This means that when the worker calls Report(), the ProgressProperty is automatically updated with the new value, and hence can be reflected in the UI. Finally your worker method is invoked with await so that the UI is able to update on every incremented value.

For a very full explanation on Progress, see Stephen Cleary's blog

这篇关于在 WPF C# MVVM 中使用进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆