I have a listview which so far has worked fine. The problem I encountered was that sometimes it would take a few seconds to populate as I was looking at adding many 1000s of items.
So I decided to populate the ListView with a BackgroundWorker, but the problem I encountered was that I could not use a control from the UI thread on the BackgroundWorker thread.
To solve that problem I wrote the code you see below. I know the returned ListView is full of items, but when I assign it to my ListView component in my form, nothing is displayed and I do not know why.
Please help me before I start slapping myself 🙂
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();
}
Thank you
Crouz
I suspect the problem may be that your are creating the
ListViewin a background thread, making that the effective UI thread for theListView.Perhaps use the background thread to return only the list of items, and assign them to the
ListViewin the UI thread.Your backgroundworker work method should return a
List<string>of the filenames, and in the backgroundworker completed event you should useListView.Items.Addrangeto add the filenames to theListView