2011-12-11 21 views
4

首先,我想讓大家都知道,我開始學習C#作爲我的第一種編程方法,所以我是一個絕對的初學者最開心的人,他在2個月前開始編碼,所以請裸露跟我。如何在事件外使用事件參數

所以我試圖做的是創建一個自定義的下載應用程序。它的所有工作除了下載全部按鈕,無法從「DownloadProgressChangedEventArgs」中選取「percent1」變量。我在mainForm構造函數之前實例化了它,但它不會讀取更改的值。

下面的代碼,因爲大多數的它不是有關的問題部分剝離:

public partial class Main : Form 
{ 
//Variables (not all, just the one im having issues with) 
    private double percentage1; 

//Main form constructor 
    public Main(){...} 

//Download File Async custom method 
    public void DldFile(string url, string fileName, string localPath, AsyncCompletedEventHandler completedName, DownloadProgressChangedEventHandler progressName) 
    { 
      WebClient webClient = new WebClient(); 
      webClient.DownloadFileAsync(new Uri(url), localPath + "\\" + fileName); 
      webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(completedName); 
      webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(progressName); 
    } 

//Button 1 click event to start download 
    private void btnDld1_Click(object sender, EventArgs e) 
    { 
     if (url1 != "" && Directory.Exists(localPath1)) 
     { 
      _startDate1 = DateTime.Now; 
      DldFile(url1, fileName1, localPath1, completed1, progress1); 
     } 
     //took out the try/catch, other ifs to try and cut it down 
    } 

//Download Progress Changed event for Download 1 
    public void progress1(object sender, DownloadProgressChangedEventArgs e) 
    { 
     percentage1 = e.ProgressPercentage; //THIS IS WHERE I WAS EXPECTING TO UPDATE "percentage1" 
     progressBar1.Value = int.Parse(Math.Truncate(percentage1).ToString()); 
    } 

//Button that starts all downloads click event where all my problems are at the moment 
    private void btnDldAll_Click(object sender, EventArgs e) 
    { 
     //The progress bar that should let me know the global status for all webClients 
     progressBarAll.Value = (
      int.Parse(Math.Truncate(percentage1).ToString()) + //HERE IS MY PROBLEM 
      int.Parse(Math.Truncate(percentage2).ToString()) + //HERE IS MY PROBLEM 
      int.Parse(Math.Truncate(percentage3).ToString()) + //HERE IS MY PROBLEM 
      int.Parse(Math.Truncate(percentage4).ToString()) + //HERE IS MY PROBLEM 
      int.Parse(Math.Truncate(percentage5).ToString()))/5; //HERE IS MY PROBLEM 

     //Checks if the link exists and starts it from the download button click event 
     if (url1 != "") 
     { 
      btnDld1.PerformClick(); 
     } 
     //Continues for url2, 3, 4, 5 and else 
    } 
} 

所以這是我找到讓你的最短途徑知道我在試圖拉斷,如果有什麼東西失蹤請讓我知道,我會盡可能快地添加任何信息。

我試圖實例化「progress1」嘗試和訪問其percentage1變量,但它沒有奏效。我試着用webClient做同樣的事情,但也沒有工作。我用谷歌和stackflow搜索無濟於事。所以我不知道這個問題是否太愚蠢,或者有一種不同的方式來看待完全不在我心中的問題。

所以主要問題是更新「百分比1」變量並使用它。 關於「progressBarAll.Value」計算還有其他一些問題,當我能夠掌握正確的值時,這些問題將得到解決。所以如果你看到它,就不用擔心。

我很抱歉這麼長的帖子,但我不知道問題出在哪裏,所以我不得不給你更多的信息,以確保我沒有搞錯別的。

快樂編碼; d

+0

好吧,這是一個很好的問題,我不想添加它,所以這篇文章只針對一個問題,然後我會試圖找出更進一步。但是這個想法是根據任何正在運行的下載來保持「progressBarAll」更新。如果dld1正在進行,那麼它會顯示download1進度,如果超過1,它將顯示所有工作下載的平均值。但我想我可以把它關閉一旦我得到一個事件處理程序外的e.Percentage值的hanlde。 –

+0

它究竟是不是工作,DownloadProgressChanged事件從未被解僱,或變量從未分配?嘗試在'progress1()'上放置一個斷點,看它是否被命中。然後逐步調試以追查實際問題。據我所知,您在這裏沒有做錯任何事情,您應該可以從事件處理程序中設置percentage1而不會出現任何問題。 – aevitas

+0

@Aevitas - 我按照你所說的設置了斷點,而我所看到的讓我更加困惑,發生了一些奇怪的事情。當我點擊下載時,所有的事件處理程序被觸發。但是變量'percentage1'與'e.ProgressPercentage'事件參數有一個不同的值,即使我在'progress1()'中聲明'percentage1 = e.ProgressPercentage'。即使我可以看到「百分比*」的值都在變化,progressBarAll根本不會移動。 –

回答

2

儘量不要去想「使用事件之外的事件參數」。考慮更新您的表單狀態。

使用屬性來簡化更新邏輯:

public partial class Main : Form 
{ 
    private double percentage1; 
    private double percentage2; 
    private double percentage3; 
    private double percentage4; 
    private double percentage5; 

    private double Percentage1 
    { 
    get 
    { 
     return this.percentage1; 
    } 
    set 
    { 
     this.percentage1 = value; 
     this.UpdatePercentageAll(); // this will update overall progress whenever the first one changes 

     progressBar1.Value = GetValueFromPercentage(value); 
    } 
    } 
    private double Percentage2 
    // same code as for Percentage1 

    void UpdatePercentageAll() 
    { 
    this.PercentageAll = (this.Percentage1 + this.Percentage2 + this.Percentage3 + this.Percentage4 + this.Percentage5)/5; 
    } 

    static int GetValueFromPercentage(double percentage) 
    { 
    return (int)Math.Truncate(percentage); 
    } 

    double percentageAll; 
    private double PercentageAll 
    { 
    get 
    { 
     return this.percentageAll; 
    } 
    set 
    { 
     this.percentageAll = value; 

     progressBarAll.Value = GetValueFromPercentage(value); 
    } 
    } 

    //Download File Async custom method 
    public void DldFile(string url, string fileName, string localPath, AsyncCompletedEventHandler completedName, DownloadProgressChangedEventHandler progressName) 
    { 
    WebClient webClient = new WebClient(); 
    webClient.DownloadFileAsync(new Uri(url), localPath + "\\" + fileName); 
    webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(completedName); 
    webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(progressName); 
    } 

    //Button 1 click event to start download 
    private void btnDld1_Click(object sender, EventArgs e) 
    { 
    if (url1 != "" && Directory.Exists(localPath1)) 
    { 
     this.StartDownloadFile1(); 
    } 
    //took out the try/catch, other ifs to try and cut it down 
    } 
    void StartDownloadFile1() 
    { 
     this.Percentage1 = 0; 
     _startDate1 = DateTime.Now; 
     DldFile(url1, fileName1, localPath1, completed1, progress1); 
    } 
    //Download Progress Changed event for Download 1 
    public void progress1(object sender, DownloadProgressChangedEventArgs e) 
    { 
    this.Percentage1 = e.ProgressPercentage; // update property, not field 

    //this will be done in property setters 
    //progressBar1.Value = int.Parse(Math.Truncate(percentage1).ToString()); 
    } 
    // then add similar code for other download buttons 

    //Button that starts all downloads click event where all my problems are at the moment 
    private void btnDldAll_Click(object sender, EventArgs e) 
    { 
    //Checks if the link exists and starts it from the download button click event 
    if (url1 != "") 
    { 
     this.StartDownloadFile1(); 
    } 
    //Continues for url2, 3, 4, 5 and else 
    } 
} 

我將進一步重構代碼,但我認爲這將是您更容易理解,如果代碼是更接近原始。

主要想法是創建一組鏈接屬性,它們像數學函數一樣工作。當編寫PercentageX屬性時,我有點'讓PercentageAll成爲所有百分比的平均值'。然後我每次下載更新它都是自己的進步。一旦任何進度更新,它會更新平均值,,我不必在改變進度的事件處理程序中記住

最後一點是從百分比屬性更新進度欄。這很簡單:一旦百分比發生變化,我需要更新一個欄。如果是這樣,爲什麼還要像

this.Percentage1 = x; 
this.progressBar1.Value = (int)Math.Truncate(x); 

寫的東西在這種情況下,我必須記住到處,一旦我改變Percentage1我必須更新吧。在我的例子中,我只是爲了那個只在一個地方並且每次都工作的地方創建一個嚴格的規則。所以我不能忘記它。如果我需要改變規則,我只需要改變一個地方,所以我再也不會犯錯。

我演示的技術可以表達爲一個衆所周知的規則:'一個規則 - 一個地方',這意味着您應該嘗試在代碼中只有一個位置,以表示程序中存在的每個邏輯規則。這是一個非常重要的想法,我建議你學習和使用它。

+0

Pavel我不太瞭解你發佈的代碼的機制。我沒有任何關於你的帖子的具體問題,即時通訊太缺乏經驗,無法一次搞定。所以即時打印出來,瞭解一切,測試它,然後再次回覆。但即時消息幾乎肯定你會得到接受的答案,謝謝你的快速答案; D –

+0

我剛剛通過代碼,我想你忘了輸入'GetValueFromPercentage(value)'方法。另一方面,我不知道,但我有一個progressBar每下載+ progressBarAll,所以單個progressBars將根據自己的下載,並progressBarAll將根據任何下載正在發生的總比例移動。從閱讀你的代碼,我認爲你試圖使用1progressBar來通知任何下載發生。讓我知道,如果我理解你correclty。 –

+0

@FernandoSilva對不起,我應該寫一個更完整的代碼。我剛剛錯過了'GetValueFromPercentage'方法。你說得對,我明白你只有一個進度條來進行所有的下載。我已經更新了代碼和答案。請檢查一下。 –