进度条常用在加载,下载,导出一些比较耗时的地方,利用进度条能让用户看到实时进展,能有更好的用户体验……
直接开始
新建一个wpf项目,然后在主窗口添加一个按钮,用来控制进度的开始。加一个进度条控件progressbar。双击按钮,为按钮添加事件,代码直接循环模仿进度的进行……
privatevoidbutton4_Click(objectsender, RoutedEventArgse){ for (inti=0; i<=100; i++) { //当前进度,最大值默认100progressBar1.Value=i; Thread.Sleep(10); } }
最简单的进度条已经完成,好的,这里运行程序执行,你会发现一个问题,点开始之后,界面直接卡住,回过神来,进度条已经满了,这和我们想像有点也不一样啊。你在ui线程里面执行了耗时的操作,就会让界面进入假死状态,这时候我们就要改进一下,使用多线程。
多线程开始
我们重新开启一个线程来模仿进度条进度,在按钮的点击事件下进行调用。好了,这次在点击按钮,我们可以看到进度条正常的显示进度情况了,不错,不错,是这种效果。
privatevoidProgressBegin() { Threadthread=newThread(newThreadStart(() => { for (inti=0; i<=100; i++) { this.progressBar1.Dispatcher.BeginInvoke((ThreadStart)delegate{ this.progressBar1.Value=i; }); Thread.Sleep(100); } })); thread.Start(); }
新窗口来一个
这个写法是一样的,只不过在新窗口弄一个,用弹窗的方式来显示,有时候还是会用到的。新建一个wpf窗口,同样加入一个进度条控件,在主窗口的按钮点击事件中写入新窗口的创建和显示,在新窗口的构造函数中调用,进度条开始进度的方法。
//window1.xaml<Windowx:Class="progressbartest.Window1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Window1"Height="217"Width="300"><Grid><ProgressBarHeight="24"HorizontalAlignment="Left"Margin="12,72,0,0"Name="progressBar1"VerticalAlignment="Top"Width="254"Foreground="#FF2EAFF1"/></Grid></Window>//window1.xaml.csusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Data;usingSystem.Windows.Documents;usingSystem.Windows.Input;usingSystem.Windows.Media;usingSystem.Windows.Media.Imaging;usingSystem.Windows.Shapes;usingSystem.Threading;namespaceprogressbartest{ /// <summary>/// Window1.xaml 的交互逻辑/// </summary>publicpartialclassWindow1 : Window { publicWindow1() { InitializeComponent(); ProgressBegin(); } privatevoidProgressBegin() { Threadthread=newThread(newThreadStart(() => { for (inti=0; i<=100; i++) { this.progressBar1.Dispatcher.BeginInvoke((ThreadStart)delegate { this.progressBar1.Value=i; }); Thread.Sleep(100); } })); thread.Start(); } } }
BackgroundWork方式
BackgroundWorker类允许您在单独的线程上执行某个可能导致用户界面(UI)停止响应的耗时操作(比如文件下载数据库事务等),并且想要一个响应式的UI来反应当前耗时操作的进度。 那岂不是用来做进度条再合适不过了,可以利用单独线程来执行耗时操作,还能反应操作的进度。
当然,如果你要使用它提供的方法,必须要先设置一下它的某些属性,不然就没法使用,比如:要使用ReportProgress()(报告进度)的方法,先要设置WorkerReportsProgress=true。其他的设置,可以查官方文档哦。
privateBackgroundWorkerbgworker=newBackgroundWorker(); privatevoidbutton3_Click(objectsender, RoutedEventArgse) { InitWork(); bgworker.RunWorkerAsync(); } /// <summary>/// 初始化bgwork/// </summary>privatevoidInitWork() { bgworker.WorkerReportsProgress=true; bgworker.DoWork+=newDoWorkEventHandler(DoWork); bgworker.ProgressChanged+=newProgressChangedEventHandler(BgworkChange); } privatevoidDoWork(objectsender, DoWorkEventArgse) { for (inti=0; i<=100; i++) { bgworker.ReportProgress(i); Thread.Sleep(100); } } /// <summary>///改变进度条的值/// </summary>privatevoidBgworkChange(objectsender, ProgressChangedEventArgse) { this.progressBar1.Value=e.ProgressPercentage; }
源代码
//mainwindow.xaml<Windowx:Class="progressbartest.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow"Height="350"Width="525"><Grid><ProgressBarHeight="23"HorizontalAlignment="Left"Margin="32,124,0,0"Name="progressBar1"VerticalAlignment="Top"Width="432"/><ButtonContent="多线程开始"Height="23"HorizontalAlignment="Left"Margin="123,54,0,0"Name="button1"VerticalAlignment="Top"Width="75"Click="button1_Click"/><ButtonContent="新窗口开始"Height="23"HorizontalAlignment="Left"Margin="219,54,0,0"Name="button2"VerticalAlignment="Top"Width="75"Click="button2_Click"/><ButtonContent="BackgroundWorker方式"Height="23"HorizontalAlignment="Left"Margin="310,54,0,0"Name="button3"VerticalAlignment="Top"Width="154"Click="button3_Click"/><ButtonContent="开始"Height="23"HorizontalAlignment="Left"Margin="32,54,0,0"Name="button4"VerticalAlignment="Top"Width="75"Click="button4_Click"/></Grid></Window>//mainwindow.xaml.csusingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Data; usingSystem.Windows.Documents; usingSystem.Windows.Input; usingSystem.Windows.Media; usingSystem.Windows.Media.Imaging; usingSystem.Windows.Navigation; usingSystem.Windows.Shapes; usingSystem.Threading; usingSystem.ComponentModel; namespaceprogressbartest{ /// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>publicpartialclassMainWindow : Window { privateBackgroundWorkerbgworker=newBackgroundWorker(); publicMainWindow() { InitializeComponent(); } privatevoidbutton1_Click(objectsender, RoutedEventArgse) { ProgressBegin(); } privatevoidProgressBegin() { Threadthread=newThread(newThreadStart(() => { for (inti=0; i<=100; i++) { this.progressBar1.Dispatcher.BeginInvoke((ThreadStart)delegate{ this.progressBar1.Value=i; }); Thread.Sleep(100); } })); thread.Start(); } privatevoidbutton2_Click(objectsender, RoutedEventArgse) { Window1window=newWindow1(); window.Show(); } /// <summary>/// 初始化bgwork/// </summary>privatevoidInitWork() { bgworker.WorkerReportsProgress=true; bgworker.DoWork+=newDoWorkEventHandler(DoWork); bgworker.ProgressChanged+=newProgressChangedEventHandler(BgworkChange); } privatevoidDoWork(objectsender, DoWorkEventArgse) { for (inti=0; i<=100; i++) { bgworker.ReportProgress(i); Thread.Sleep(100); } } /// <summary>///改变进度条的值/// </summary>privatevoidBgworkChange(objectsender, ProgressChangedEventArgse) { this.progressBar1.Value=e.ProgressPercentage; } privatevoidbutton3_Click(objectsender, RoutedEventArgse) { InitWork(); bgworker.RunWorkerAsync(); } privatevoidbutton4_Click(objectsender, RoutedEventArgse) { for (inti=0; i<=100; i++) { progressBar1.Value=i; Thread.Sleep(10); } } } } //window1.xaml<Windowx:Class="progressbartest.Window1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Window1"Height="217"Width="300"><Grid><ProgressBarHeight="24"HorizontalAlignment="Left"Margin="12,72,0,0"Name="progressBar1"VerticalAlignment="Top"Width="254"Foreground="#FF2EAFF1"/></Grid></Window>//window1.xaml.csusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Data;usingSystem.Windows.Documents;usingSystem.Windows.Input;usingSystem.Windows.Media;usingSystem.Windows.Media.Imaging;usingSystem.Windows.Shapes;usingSystem.Threading;namespaceprogressbartest{ /// <summary>/// Window1.xaml 的交互逻辑/// </summary>publicpartialclassWindow1 : Window { publicWindow1() { InitializeComponent(); ProgressBegin(); } privatevoidProgressBegin() { Threadthread=newThread(newThreadStart(() => { for (inti=0; i<=100; i++) { this.progressBar1.Dispatcher.BeginInvoke((ThreadStart)delegate { this.progressBar1.Value=i; }); Thread.Sleep(100); } })); thread.Start(); } } }
参考资料
BackgroundWorker使用总结
https://blog.csdn.net/coderookieguo/article/details/72723310