場景 在Winform中實現彈窗式進度條 就是新建一個窗體,然後在窗體中加入進度條控制項,然後在觸發進度條的事件中將載入進度報告給 進度條控制項。 註: 博客主頁: https://blog.csdn.net/badao_liumang_qizhi 關註公眾號 霸道的程式猿 獲取編程相關電子書、教程推送 ...
場景
在Winform中實現彈窗式進度條
就是新建一個窗體,然後在窗體中加入進度條控制項,然後在觸發進度條的事件中將載入進度報告給
進度條控制項。
註:
博客主頁:
https://blog.csdn.net/badao_liumang_qizhi
關註公眾號
霸道的程式猿
獲取編程相關電子書、教程推送與免費下載。
實現
設計進度條窗體
新建窗體FrmProgressBar,打開設計頁面,打開DevExpress的工具箱。
拖拽一個SplashScreen控制項
然後再拖拽一個label和MarqueeProgressBarControl控制項
然後打開其代碼頁面,編輯其代碼為
public partial class FrmProgressBar : SplashScreen { #region 單例實現 private static string _lockFlag = "FrmProgressBarLock"; private static FrmProgressBar _instance = null; /// <summary> /// 進度條視窗實例 /// </summary> public static FrmProgressBar Instance { get { lock(_lockFlag) { if (_instance == null) { _instance = new FrmProgressBar(true); } else if (_instance.IsDisposed) { _instance = null; _instance = new FrmProgressBar(true); } return _instance; } } } #endregion #region 欄位定義 private bool _isShowTitle = false; #endregion #region 構造方法 private FrmProgressBar() { InitializeComponent(); } private FrmProgressBar(bool isShowTitle) { InitializeComponent(); this._isShowTitle = isShowTitle; this.marqueeProgressBarControl1.Properties.ShowTitle = this._isShowTitle; } #endregion #region 屬性定義 /// <summary> /// 是否顯示標題 /// </summary> public bool IsShowTitle { get { return this._isShowTitle; } set { this._isShowTitle = value; this.marqueeProgressBarControl1.Properties.ShowTitle = this._isShowTitle; } } /// <summary> /// 提示文本 /// </summary> public string NotifyText { get { return this.labelControl2.Text; } set { this.labelControl2.Text = value; } } /// <summary> /// 進度值 /// </summary> public int ProgressValue { get { return (int)this.marqueeProgressBarControl1.EditValue; } set { this.marqueeProgressBarControl1.Text = String.Format("{0}%", value); } } #endregion #region Overrides public override void ProcessCommand(Enum cmd, object arg) { base.ProcessCommand(cmd, arg); } #endregion public enum SplashScreenCommand { } }
調用進度條窗體
需要新開一個線程去執行進度條所代表的任務,在觸發進度條的事件中
BackgroundWorker bgWorker = new BackgroundWorker();
並且設置其是否報告進度屬性為true
bgWorker.WorkerReportsProgress = true;
然後綁定具體的進度條所代表的任務
bgWorker.DoWork -= backgroundWorker1_DoWork;
bgWorker.DoWork += backgroundWorker1_DoWork;
在此綁定的方法中就會執行具體的任務
然後設置任務進度改變的事件綁定
bgWorker.ProgressChanged -= bgWorker_ProgressChanged;
bgWorker.ProgressChanged += bgWorker_ProgressChanged;
在此方法中進行進度條進度與任務執行進度的綁定
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (e.ProgressPercentage >= 0 && e.ProgressPercentage <= 100) { Dialog.FrmProgressBar.Instance.ProgressValue = e.ProgressPercentage; } }
然後設置任務執行完之後關閉進度條視窗
bgWorker.RunWorkerCompleted -= bgWorker_RunWorkerCompleted;
bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;
在執行完的方法中
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Dialog.FrmProgressBar.Instance.Dispose(); //關閉進度對話框 }
然後開始執行後臺操作
bgWorker.RunWorkerAsync();
然後最後讓進度條窗體顯示
Dialog.FrmProgressBar.Instance.ShowDialog();
需要註意的是:
在DoWork 中綁定的具體的執行的任務中一定是佷費時間的任務,如果就是簡單的
幾個for迴圈,那麼會看不到效果,因為這兩個線程沒有時間差,所以會同時顯示與關閉。
所以在具體執行的後臺任務中要執行有時間差的任務,比如讀取大數據量文件。
並且在執行此任務時要根據執行的任務進度去進行報告。
在DoWork綁定的方法中
BackgroundWorker bgWorker = sender as BackgroundWorker; 。。。 bgWorker.ReportProgress(10); //10% 。。。 bgWorker.ReportProgress(65); 。。。 bgWorker.ReportProgress(100);
完整示例代碼
//創建新的後臺線程 BackgroundWorker bgWorker = new BackgroundWorker(); //設置線程是否報告進度為true bgWorker.WorkerReportsProgress = true; //綁定具體的後臺任務的方法,在此方法中會報告進度 bgWorker.DoWork -= backgroundWorker1_DoWork; bgWorker.DoWork += backgroundWorker1_DoWork; //當進度改變時事件綁定,將綁定的進度作為進度條的進度 bgWorker.ProgressChanged -= bgWorker_ProgressChanged; bgWorker.ProgressChanged += bgWorker_ProgressChanged; //後臺線程執行完事件綁定,會關閉進度條視窗 bgWorker.RunWorkerCompleted -= bgWorker_RunWorkerCompleted; bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted; //開始執行後臺操作 bgWorker.RunWorkerAsync(); //顯示進度條視窗 Dialog.FrmProgressBar.Instance.ShowDialog();
執行後臺任務的方法
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker bgWorker = sender as BackgroundWorker; List<Cycle> cycles = null; List<Step> steps = null; List<Record> mainRecords = null; bgWorker.ReportProgress(10); //10% #region 載入迴圈數據 string cycleDataFile = String.Format("{0}{1}", Global.Instance.CurrDataFile, Global.CYCLE_EXT); if (System.IO.File.Exists(cycleDataFile)) { using (System.IO.Stream fs = new System.IO.FileStream(cycleDataFile, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { cycles = ProtoBuf.Serializer.Deserialize<List<Cycle>>(fs); } } bgWorker.ReportProgress(40); #endregion #region 載入工步數據 string stepDataFile = String.Format("{0}{1}", Global.Instance.CurrDataFile, Global.STEP_EXT); if (System.IO.File.Exists(stepDataFile)) { using (System.IO.Stream fs = new System.IO.FileStream(stepDataFile, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { steps = ProtoBuf.Serializer.Deserialize<List<Step>>(fs); } } bgWorker.ReportProgress(70); #endregion #region 載入主通道數據 string mainRecordDataFile = String.Format("{0}{1}", Global.Instance.CurrDataFile, Global.MAIN_EXT); if (System.IO.File.Exists(mainRecordDataFile)) { using (System.IO.Stream fs = new System.IO.FileStream(mainRecordDataFile, System.IO.FileMode.Open, System.IO.FileAccess.Read)) { mainRecords = ProtoBuf.Serializer.Deserialize<List<Record>>(fs); } } #endregion bgWorker.ReportProgress(100); }
後臺任務進度改變事件
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (e.ProgressPercentage >= 0 && e.ProgressPercentage <= 100) { Dialog.FrmProgressBar.Instance.ProgressValue = e.ProgressPercentage; } }
後臺任務執行完畢事件
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Dialog.FrmProgressBar.Instance.Dispose(); //關閉進度對話框 }