如何在事件之外使用事件参数

本文关键字:事件 参数 | 更新日期: 2023-09-27 18:17:34

我正在尝试创建一个自定义下载应用程序。除了下载所有按钮不能从"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搜索,但都无济于事。所以我不确定是这个问题太愚蠢了,还是有一种不同的方式来看待这个问题,而这完全超出了我的思维方式。

所以主要问题是更新"percentage1"变量并使用它。关于"progressBarAll"还有其他问题。当我能得到正确的值时,"值"计算将得到解决。所以不用担心,如果你看到了

如何在事件之外使用事件参数

尽量不要考虑'在事件之外使用事件参数'。考虑更新表单的状态。

使用属性简化更新逻辑:

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,我必须更新栏。在我的例子中,我只是创建了一个严格的规则,只在一个地方,每次都有效。所以我不能忘记它。如果我需要改变规则,我只需要改变一个地方,这样我就不会出错了。

我演示的技术可以用一个众所周知的规则来表达:"一个规则-一个地方",这意味着你应该尝试在代码中只有一个地方来表达程序中存在的每个逻辑规则。这是一个非常重要的想法,我建议你学习和使用它。