如何在方法中使用值为 += 的 Progressbar?

How to use the Progressbar with value += in a method?

我想创建一个进度条。我设置进度条的值+=一个值(比如+=5)。开始时值 = 0.

XAML代码。

<ProgressBar x:Name="pgbStatus" Minimum="0" Maximum="100" />

我想这样设置进度条的值:

pgbStatus.Value += 10;

方法中有很多这样的行来设置值。

但是如果我启动程序,进度条会显示 0 值(=空),最后显示 100 值(=满)。

为什么进度条不显示中间的步骤?

我的方法看起来像(如果消息框出现,进度条显示 100 =full):

public void Method() {
    //do something
    pgbStatus.Value += 10;
    //do something
    pgbStatus.Value += 10;
    //do something
    MessageBox.Show("Finished");
    pgbStatus.Value = 0;
}

当程序为运行时,这将在单步执行。 为了解决这个问题,您应该随时使用全局 int 变量来保存进度百分比(如 int percent = 0)并在您的代码中更新它。

然后,你应该使用一个计时器(如Timer MyTimer),它在指定的时间间隔内(例如每 100 毫秒)更新进度值,并且在每个时间间隔内,使用这个:(把它放在 MyTimer_Tick 事件)

progressbar.Value = percent.
if(percent>=100)
{
    MessageBox.Show("Finished!");
    MyTimer.Enabled = false;
}

由此,程序运行两个线程并更新进度值。

执行此操作并查看结果。

希望对您有所帮助。

<Window x:Class="WpfTutorialSamples.Misc_controls.ProgressBarTaskOnUiThread"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ProgressBarTaskOnUiThread" Height="100" Width="300"
    ContentRendered="Window_ContentRendered">
<Grid Margin="20">
    <ProgressBar Minimum="0" Maximum="100" Name="pbStatus" />
</Grid>

            private void This_is_Your_Button_Click_EVENT(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)
            {
                    for(int i = 0; i < 100; i++)
                    {
                            (sender as BackgroundWorker).ReportProgress(i);
                            Thread.Sleep(100);
                    }
            }

            void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                    pbStatus.Value = e.ProgressPercentage;
            }

Ui 线程没有时间更新 UI,因此您需要给 UI 线程一些时间来进行 UI 更新。为此,您必须以异步方式完成工作。你可以使用 await 和 async。我已将您的方法更新如下:

    public async void Method()
    {
        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        //do something
        await Task.Delay(1000);
        pgbStatus.Value += 10;

        MessageBox.Show("Finished");
        pgbStatus.Value = 0;
    }

而不是 Task.delay(1000) 你可以把你的代码

我想再多一个答案不会有什么坏处...

在按钮单击处理程序中,运行 您的 "Method" 在另一个线程上。当你需要更新进度条时,使用它的Dispatcher来增加值(dispatcher运行是UI线程上的代码)。

单击事件处理程序:

private async void btnMethod_Click(object sender, RoutedEventArgs e)
{
    pgbStatus.Value = 0;
    await Task.Run((Action)Method);
    MessageBox.Show("Finished");
    pgbStatus.Value = 0;
}

以及更新后的方法,方法:

public void Method()
{
    System.Threading.Thread.Sleep(500); // do something
    pgbStatus.Dispatcher.Invoke(() => pgbStatus.Value += 10);
    System.Threading.Thread.Sleep(500); // do something
    pgbStatus.Dispatcher.Invoke(() => pgbStatus.Value += 10);
    System.Threading.Thread.Sleep(500); // do something
    pgbStatus.Dispatcher.Invoke(() => pgbStatus.Value += 60);
    System.Threading.Thread.Sleep(500); // do something
    pgbStatus.Dispatcher.Invoke(() => pgbStatus.Value += 10);
    System.Threading.Thread.Sleep(500); // do something
    pgbStatus.Dispatcher.Invoke(() => pgbStatus.Value += 10);
}

首先,我们需要创建一个数据绑定。在 xaml:

<ProgressBar x:Name="pgbStatus" Minimum="0" Maximum="100" Value="{Binding Path=ProgBarValue}"/>

现在我们为绑定创建一个 class:

public class AuxBindings : INotifyPropertyChanged
{
    public AuxBindings()
    {
        ProgBarValue=0;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    private int progBarValue;
    public int ProgBarValue
    {
        get
        {
            return progBarValue;
        }
        set
        {
            progBarValue = value;
            NotifyPropertyChanged();
        }
    }
}

在您的主 windows 后面的代码中,我们将 class 的一个实例与绑定相关联:

AuxBindings a = new AuxBindings();

public MainWindow()
{
    InitializeComponent();
    pgbStatus.DataContext=a;
}

现在我们要做的就是创建一个新的线程来执行,所有你需要做的值修改,你只需要改变属性的值:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Task.Run(()=>
        {
            Method();
        }
    );
}

public void Method() {
    //do something
    a.progBarValue += 10;
    //do something
    a.progBarValue += 10;
    //do something
    MessageBox.Show("Finished");
    a.progBarValue = 0;
}