繁体   English   中英

以父表格控制的事件

[英]Event operating on control in parent form

我有一些文件可以从ftp服务器下载。 我想要实现的是:

  1. 有一个SplitContainer ,在MainForm其中一个面板中有ListView
  2. 我想获取要下载的文件列表,为该ListView每个文件创建一个ProgressBar和一个Label
  3. ProgressChanged事件,我想显示文件对目前的进展ProgressBar上和当前的下载速度Label

这是我的代码的最新版本:

internal async Task GetFiles(IEnumerable<string> urlList)
{
    string dir = Environment.CurrentDirectory + "\\updates";
    Directory.CreateDirectory(dir);
    var tasks = new List<Task>();

    foreach (var url in urlList)
        tasks.Add(DownloadFile(url, dir));

    await Task.WhenAll(tasks);
}

internal async Task DownloadFile(string url, string dir)
{
    string filename = Helper.GetFilenameFromUrl(url);
    ProgressBar pb = CreateFileDownloadBar();
    Label lb = CreateFileDownloadLabel();
    Stopwatch sw = new Stopwatch();
    Helper.CrossThreadInvoke(_sender, () => _sender.listView1.Controls.Add(pb));
    Helper.CrossThreadInvoke(_sender, () => _sender.listView1.Controls.Add(lb));

    using (var client = new WebClient())
    {
        client.DownloadProgressChanged += new DownloadProgressChangedEventHandler((sender, e) => ProgressChanged(sender, e, sw, pb, lb));
        client.DownloadFileCompleted += new AsyncCompletedEventHandler((sender, e) => Completed(sender, e, sw));
        Helper.CrossThreadInvoke(_sender, () => _sender.lblFileDownload.Text = Helper.GetFilenameFromUrl(url));
        await client.DownloadFileTaskAsync(url, string.Concat(dir, "\\", filename));
    }
}

private Label CreateFileDownloadLabel()
{
    Label lb = new Label()
    {
        Location = new System.Drawing.Point(_sender.offset - 180, 5 + offset)
    };
    return lb;
}

private ProgressBar CreateFileDownloadBar()
{
    ProgressBar pb = new ProgressBar()
    {
        Location = new System.Drawing.Point(5, 5 + offset),
        Size = new System.Drawing.Size(200, 20)
    };

    offset += pb.Height + 5;

    return pb;
}

private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e, Stopwatch sw, ProgressBar pb, Label lb)
{
    pb.Value = e.ProgressPercentage;
    lb.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00"));        
}

但是,该事件中的pblb不会更新MainForm控件。 我怀疑是因为我操作它的本地副本,而不是我添加到MainForm的那些副本,但我不知道如何让它工作。 我是否需要某种类似于CrossThreadInvoke的计数器

ProgressBar pb = Helper.CrossThreadInvoke(_sender, () => _sender.listView1.Controls[counter] as ProgressBar;
pb.Value = e.ProgressPercentage;

然而,这似乎是不必要的复杂,所以我想知道是否有更好的方法。

我给你做了一个小例子,它真的不漂亮,但应该让你知道如何实现进步。

我也评论了很多东西并插入了一些演示代码。

关键是使用Controls.Invoke() - 方法,如果你在不同的线程/任务。

public partial class Form1 : Form {


    public Form1() {

      InitializeComponent();
      var l = new List<string>();
      for (int i = 0; i < 10; i++) {
        l.Add("Some Text" + i);
      }
      Task.Factory.StartNew(async () => {
        await GetFiles(l, this);
      });
    }



    private int ctrlCount = 0;

    public void AddControlToListView(Control c) {
      if (c is Label) {
        c.Location = new Point(205, ctrlCount * c.Height + 5);
      } else {
        c.Location = new Point(5, ctrlCount * c.Height + 5);
      }

      if (this.listView1.InvokeRequired) {
        this.listView1.Invoke(new Action<Control>(this.listView1.Controls.Add), c);
        this.listView1.Invoke(new Action(this.listView1.Update));
      } else {
        this.listView1.Controls.Add(c);
        this.listView1.Update();
      }

      ctrlCount++;
    }

    internal async Task GetFiles(IEnumerable<string> urlList, Form1 parent) {
      //string dir = Environment.CurrentDirectory + "\\updates";

      //Directory.CreateDirectory(dir);
      var tasks = new List<Task>();

      foreach (var url in urlList)
        tasks.Add(DownloadFile(url, ""));

      await Task.WhenAll(tasks);
    }



    internal async Task DownloadFile(string url, string dir) {
      string filename = "";// Helper.GetFilenameFromUrl(url);
      ProgressBar pb = CreateFileDownloadBar();
      Label lb = CreateFileDownloadLabel();
      this.AddControlToListView(pb);
      this.AddControlToListView(lb);
      Stopwatch sw = new Stopwatch();
      //Helper.CrossThreadInvoke(_sender, () => _sender.listView1.Controls.Add(pb));
      //Helper.CrossThreadInvoke(_sender, () => _sender.listView1.Controls.Add(lb));
      await Task.Factory.StartNew(() => {
        for (int i = 1; i < 11; i++) {
          pb.Invoke(new MethodInvoker(delegate {
            pb.Value = i * 10;
          }));
          lb.Invoke(new MethodInvoker(delegate {
            lb.Text = (i * 10).ToString();
          }));
          Thread.Sleep(500);
        }
      });
      using (var client = new WebClient()) {
        client.DownloadProgressChanged += new DownloadProgressChangedEventHandler((sender, e) => ProgressChanged(sender, e, sw, pb, lb));
        //client.DownloadFileCompleted += new AsyncCompletedEventHandler((sender, e) => Completed(sender, e, sw));
        //Helper.CrossThreadInvoke(_sender, () => _sender.lblFileDownload.Text = Helper.GetFilenameFromUrl(url));
        //await client.DownloadFileTaskAsync(url, string.Concat(dir, "\\", filename));
      }
    }

    private Label CreateFileDownloadLabel() {
      Label lb = new Label() {
        Text = "Hello"
        //Location = new System.Drawing.Point(_sender.offset - 180, 5 + offset)
      };
      return lb;
    }

    private ProgressBar CreateFileDownloadBar() {
      ProgressBar pb = new ProgressBar() {
        //Location = new System.Drawing.Point(5, 5 + offset),
        Size = new System.Drawing.Size(200, 20)
      };

      //offset += pb.Height + 5;

      return pb;
    }

    private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e, Stopwatch sw, ProgressBar pb, Label lb) {
      pb.Value = e.ProgressPercentage;
      lb.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00"));
    }  

}

我希望这能让您了解如何创建和更新ProgressBars

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM