如何在方法中使用值为 += 的 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;
}
我想创建一个进度条。我设置进度条的值+=一个值(比如+=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;
}