无法从backgroundworker分配返回的ListView

时间:2012-11-28 15:03:46

标签: c#

我有一个列表视图,到目前为止工作正常。我遇到的问题是,有时需要几秒钟才能填充,因为我正在考虑添加1000多个项目。

所以我决定使用BackgroundWorker填充ListView,但我遇到的问题是我无法使用BackgroundWorker线程上的UI线程中的控件。

为了解决这个问题,我编写了下面你看到的代码。我知道返回的ListView中有很多项,但是当我在表单中将它分配给我的ListView组件时,没有显示任何内容,我不知道为什么。

在我开始拍打自己之前请帮助我:)

public ListView listImages(string path, BackgroundWorker worker)
{
    ListView lv = new ListView();
    lv.Items.Clear();
    int count = 0;
    int total = 0;
    string[] extensions = new string[] { ".jpg", ".JPG", ".png", ".PNG", ".bmp", ".BMP" };
    lv.Columns.Add("Filename", 300);
    lv.Columns.Add("Date taken", 150);
    lv.Columns.Add("Size", 150);
    DirectoryInfo dir = new DirectoryInfo(path);
    IEnumerable<FileInfo> files = dir.EnumerateFiles("*.*", SearchOption.AllDirectories).Where(f => extensions.Contains(f.Extension));
    total = files.Count();
    foreach (FileInfo f in files)
    {
        DateTime dt = File.GetCreationTime(Path.Combine(f.Directory.ToString(), f.Name));
        string fsize = FormatBytes(f.Length);

        count++;
        ListViewItem lSingleItem = lv.Items.Add(f.Name);

        lSingleItem.SubItems.Add(dt.ToString("dd MMMM yyyy"));
        lSingleItem.SubItems.Add(fsize);
        lSingleItem.Tag = Path.Combine(f.Directory.ToString(), f.Name);


        worker.ReportProgress((count * 100) / total);
    }
    return lv;
}

private void buttonLeftBrowse_Click(object sender, EventArgs e)
{
    if (_bwListImages.IsBusy != true)
    {
        pgf = new ProgressBarForm();

        if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
        {
            string path = folderBrowserDialog.SelectedPath;
            this.textBoxLeftFolder.Text = path;
            object[] parameters = new object[] { path };

            _bwListImages.RunWorkerAsync(parameters);
            pgf.ShowDialog();
       }
    }
}

private void _bwListImages_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    object[] parameters = e.Argument as object[];
    resetViewsColor();
    disableButtons();

    e.Result = core.listImages((string)parameters[0], worker);

    checkButtons();
}

private void _bwListImages_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    pgf.progressBar.Value = e.ProgressPercentage;
}

private void _bwListImages_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    listViewLeft = (ListView)e.Result;
    pgf.Close();
}

谢谢 Crouz

3 个答案:

答案 0 :(得分:1)

我怀疑问题可能是您在后台线程中创建ListView,使其成为ListView的有效UI线程。

也许使用后台线程只返回项目列表,并将它们分配给UI线程中的ListView

您的后台工作者工作方法应该返回List<string>个文件名,并且在后台工作完成事件中,您应该使用ListView.Items.Addrange将文件名添加到ListView

答案 1 :(得分:0)

什么是listViewLeft?我猜是ListView?如果是listViewLeft.ItemsSource,则应指定wpf;如果是listViewLeft.DataSource,则应指定winform,而不是ListView

答案 2 :(得分:0)

正如Rotem指出的那样,你可以通过在工作线程(Say AssignListview)中引发事件来做到这一点,然后你可以通过以下方式将调用委托给实际的赋值  this.BeginInvoke((MethodInvoker)委托{ActualAssignmentFunction();});

ActualAssignmentFunction();在UI线程中执行。