2010-02-25 42 views
0

我正在研究一個應用程序,該應用程序具有底部狀態欄的主窗體。狀態欄包含一個ProgressBar和一個標籤,我想用它來向用戶顯示正在完成的一些工作的當前進度。狀態欄還包含一個我想要使用的標籤,如可點擊取消按鈕。將接口概括爲GUI中的進度條

我已經創建了類似這樣的異步接口,但他們一直基於一個動作,並且使用後臺工作。但是,在這個新程序中,用戶可能會啓用許多不同的操作,我希望使用同一個狀態欄來顯示所有這些操作的進度。所以我試圖找出一種方法來概括和標準化狀態欄中這些進度報告控件的界面。

在某些情況下,異步進程是使用BackGroundWorker創建的,但在其他情況下,我需要直接創建管理輔助線程。

下面是一些半成品的骨架代碼是我一直在想:

public partial class MyForm: System.Windows.Forms.Form 
{ 
    ...SNIP... 

    private void WorkProgressChanged(Object sender, EventArgs args) 
    { 
     ProgressChangedEventArgs backgroundWorkerArgs = args as ProgressChangedEventArgs; 
     ProgressReport formReport = args as ProgressReport; //my own custom progress report class 


     //tries to cast args to a Background worker args 
     if (backgroundWorkerArgs != null) 
     { 
      // update UI based on backgroundWorkerArgs 

     } 
     else if (formReport != null) 
     { 
      // update UI basd on formReport 

     } 

     else 
     { 
      //couldn't figure out what kind of progress report was sent 
      //update UI based on args.ToString(); 

     } 

    } 


    private void cancelButtonToolStripLabel_Click(object sender, EventArgs e) 
    { 
     //calls cancel method of current processing 
     if (this._currentWorkCancelAction != null) 
     { 
      _currentWorkCancelAction(); //envoke cancel requet 
      cancelButtonToolStripLabel.Text = "Canceling"; //shows user that cancel request was made 
      _currentWorkCancelAction = null; //disaccociates cancel button to prevent user from canceling twice 
     } 
    } 


    private void WorkProcessCompleted(Object sender, EventArgs args) 
    { 
     //Reset cancel button 
     cancelButtonToolStripLabel.Text = "Cancel"; 
     cancelButtonToolStripLabel.Visible = false; 

     //resets the status label and progress bar 
     statusToolStripLabel.Text = ""; 
     toolStripProgressBar.Value = 0; 


    } 

....SNIP 

} 

所以狀態欄訂閱`WorkProgressChanged(對象發件人,EventArgs參數)的一些事情 更新」,並最終當'WorkProcessCompleted(Object sender,EventArgs args)'被完成甚至包含時,重置。我的取消標籤(按鈕)也需要關聯,並在稍後與委託方法分離,該方法將要求取消當前正在進行的任何工作。

因此,每次完成工作都需要發生一堆事情。事件訂閱被添加/刪除,委託引用被改變等等..等等。所以我開始想知道是否有某種方式可以將所有這些動作封裝到一個或兩個可重用的方法中,而不是爲可能需要的每個動作編寫重複的代碼地點。

下面的InitWorkProcess()方法顯示了我如何認爲這可能工作。雖然我很確定這不是使用EventDescriptor類的正確方法。我找不出任何其他方式將事件引用爲方法參數。也許這是不可能的?

public void InitWorkProcess(EventDescriptor workProgressChangedEvent, EventDescriptor workCompletedEvent, System.Action requestCancel) 
    { 
     //subscribe to progress changed 
     workProgressChangedEvent.AddEventHandler(this, this.WorkProgressChanged); 
     this._workProgressChangedEvent = workProgressChangedEvent; 

     //subscribe to process completed 
     workCompletedEvent.AddEventHandler(this, this.WorkProcessCompleted); 
     this._workCompletedEvent = workCompletedEvent; 


     //enable cancel button 
     if (requestCancel != null) 
     { 
      cancelButtonToolStripLabel.Visible = true; 
      this._currentWorkCancelAction = requestCancel; 
     } 
    } 

...我會更改WorkProgressComplete事件處理方法,以在工作完成時取消訂閱事件關係。

private void WorkProcessCompleted(Object sender, EventArgs args) 
    { 
     //Reset cancel button 
     cancelButtonToolStripLabel.Text = "Cancel"; 
     cancelButtonToolStripLabel.Visible = false; 

     //resets the status label and progress bar 
     statusToolStripLabel.Text = ""; 
     toolStripProgressBar.Value = 0; 


     //unsubscribes WorkProcessCompleted() and WorkProgressChanged() methods 
     this._workCompletedEvent.RemoveEventHandler(this, this._workCompletedEvent); 
     this._workCompletedEvent = null; 

     this._workProgressChangedEvent.RemoveEventHandler(this, this._workProgressChangedEvent); 
     this._workProgressChangedEvent = null; 
    } 

有沒有人有任何建議,我應該如何設置?我應該忘記InitWorkProcess()方法,而是分別爲每個操作添加/刪除所有事件/委託關係?或者有更好的方法嗎?

回答

0

爲什麼不從自定義線程中使用ProgressChangedEventArgs,並利用來自任何後臺工作者的公共事件對象...而不是嘗試處理多種類型的進度報告對象?

+0

我不知道,好點。儘管我認爲我最終會遇到同樣的問題,因爲即使我將其限制爲ProgressChangedEventArgs,也沒有限制實際用於其UserState屬性的類型。 – 2010-02-25 02:17:39

+0

好的,您可以在UserState屬性中使用一致的數據類型,並使用'as'關鍵字來安全地轉換爲該類型。如果它爲null,則可以將該事件忽略爲未知進度事件。否則,您可以對任何來源的所有進度事件使用單個實現。 – jrista 2010-02-25 02:26:26

1

我不認爲進度條應該直接訂閱這些事件。

它應該實現一個接口,該接口公開Progress Bar的所有相關功能,這可以處理跨線程調用,使控件更安全。內部代碼應該不知道任何外部類型,即封裝。

「佈線」應該位於控件的公共父級中,通過公共接口將事件映射到進度條上的更改。