Как использовать аргумент события вне события - PullRequest
4 голосов
/ 11 декабря 2011

Я пытаюсь создать специальное приложение для загрузки.Все работает, кроме кнопки «загрузить все», которая не может выбрать переменную «процент1» из «DownloadProgressChangedEventArgs».Я создал его до конструктора 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», чтобы попытаться получить доступ к своей переменной процент1, но это не сработало.Я пытался сделать то же самое с webClient, но тоже не работал.Я использовал Google и поиск в стеке безрезультатно.Поэтому я не уверен, является ли вопрос слишком тупым, или есть другой способ взглянуть на проблему, которая совершенно не в моем сознании.

Так что основная проблема заключается в обновлении переменной «процент1» и ее использовании.Существуют и другие проблемы, связанные с вычислением «progressBarAll.Value», которые будут решены, когда я смогу получить правильное значение.Поэтому не стоит беспокоиться об этом, если вы это видите.

1 Ответ

2 голосов
/ 11 декабря 2011

Старайтесь не думать об «использовании аргументов события вне события».Подумайте об обновлении состояния вашей формы.

Используйте свойства, чтобы упростить логику обновления:

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, мне придется обновить панель.И в моем примере я просто создаю строгое правило для того, что только в одном месте и работает каждый раз.Так что я просто не могу забыть это.И если мне нужно изменить правило, мне нужно изменить только одно место, поэтому я снова не могу ошибиться.

Техника, которую я демонстрирую, может быть выражена в виде хорошо известного правила: «одно правило - одноplace ', что означает, что вы должны пытаться иметь только одно место в коде, которое выражает каждое логическое правило, которое существует в вашей программе.Это очень важная идея, я предлагаю вам изучить и использовать ее.

...