Listview puts the same images in every group - c#

My listview should make a group for every directory on a specified path, and add the pictures from each directory to the group that was created for it; but instead it adds the pictures from the last directory to each group.
Any ideas how can i solve this problem?
Thank you!
private void Form2_Load(object sender, EventArgs e)
{
string path = #"C:\pics\";
string[] tabs_needed = System.IO.Directory.GetDirectories(path);
foreach (string folder in tabs_needed)
{
FileInfo f = new FileInfo(folder);
listBox1.Items.Add(f.Name);
TabPage ghhk = new TabPage(f.Name);
tabControl1.Controls.Add(ghhk);
ListView listView1 = new ListView();
ghhk.Controls.Add(listView1);
listView1.Dock = DockStyle.Fill;
string new_path = path + f.Name;
string[] groups_needed =System.IO.Directory.GetDirectories(new_path);
foreach (string ufolder in groups_needed)
{
FileInfo uf = new FileInfo(ufolder);
string f_path = String.Concat(new_path + #"\" + uf.Name + #"\");
DirectoryInfo dir = new DirectoryInfo(f_path);
ImageList imagelist = new ImageList();
foreach (FileInfo file in dir.GetFiles())
{
try
{
imagelist.Images.Add(Image.FromFile(file.FullName));
}
catch
{
}
}
imagelist.ImageSize = new Size(32, 32);
listView1.View = View.LargeIcon;
ListViewGroup gr1 = new ListViewGroup(uf.Name);
listView1.Groups.Add(gr1);
string tpath = String.Concat(f_path, "gf.txt");
for (int counter = 0; counter < imagelist.Images.Count; counter++)
{
ListViewItem item = new ListViewItem();
item.Text = File.ReadAllLines(tpath).Skip(counter).Take(1).First();
item.ImageIndex = counter;
item.Group = gr1;
listView1.Items.Add(item);
}
listView1.LargeImageList = imagelist;
}

This is happening because you are instantiating the ImageList each time in the foreach loop. When you assign the imagelist finally to listView1.LargeImageList, it is only the final imagelist instance that gets attached.
You will need to move the instantiation out of the foreach loop
ImageList imagelist = new ImageList();
foreach (string ufolder in groups_needed)
{
...
}
You may also need to change the logic for your ImageIndex to get this working, now that the ImageList is out of the loop.

You should replace
listView1.LargeImageList = imagelist;
with
listView1.LargeImageList.Images.AddRange(imagelist.Images.Cast<System.Drawing.Image>().ToArray())
Because you are overwriting image list at each cycle.

Related

C# ListBox copy to Folder

I'm a newbish C#er and here's my question:
What I want:
Copy mp3 files of the same Artist into the same Folder.
e.G. Nirvana - Song 1 & Nirvana - Song 2 into Folder "Nirvana".
What I've been doing so far:
Read ParantDirectory and List the ingredients into a Listbox. The Listbox shows only the Artist (of course its filtered(Substring(indexof"-"))). After the files have been read my tool create a Folder with the Artist name.
And there I'm struggling!
I need a snippet that copy all content of Nirvana* to the Nirvana Folder.
I really hope you girls and guys understand what I'm trying to do...
Thank you in advance!
Greetings from Germany,
ceteus
edit:"here's my code"
void Button1Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
DirectoryInfo ParentDirectory = new DirectoryInfo(#"C:\Users\A7024985\Desktop\_xxx");
label1.Text = ParentDirectory.ToString();
foreach (FileInfo f in ParentDirectory.GetFiles())
{
listBox1.Items.Add(f.Name.Substring(0,f.Name.IndexOf("-"))); //nur den Dateinamen anzeigen in Listbox1
//listBox1.Items.Add(f.Name);
}
// DOPPELTE DATEIEN LĂ–SCHEN in LISTBOX
string[] temp = new string[listBox1.Items.Count];
ArrayList newList = new ArrayList();
for(int i = 0; i< listBox1.Items.Count; i++)
{
temp[i] = listBox1.Items[i].ToString();
}
foreach(string ts in temp)
{
if(!newList.Contains(ts))
{
newList.Add(ts);
}
}
listBox1.Items.Clear();
foreach(string ns in newList)
{
listBox1.Items.Add(ns.ToString());
}
foreach(var listboxitem in listBox1.Items)
{
string pfad = label1.Text + "\\" + listboxitem.ToString();
//DirectoryInfo plop = new DirectoryInfo(name);
//FileInfo[] nPath = plop.GetFiles();
try
{
bool exists = Directory.Exists(pfad);
if(!exists)
{
Directory.CreateDirectory(pfad);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
void Button2Click(object sender, EventArgs e)
{
listBox2.Items.Clear();
DirectoryInfo ParentDirectory = new DirectoryInfo(#"C:\Users\A7024985\Desktop\_xxx");
foreach (FileInfo f in ParentDirectory.GetFiles())
{
listBox2.Items.Add(f.Name.Substring(0,f.Name.IndexOf("-")));
}
foreach(var listboxitem2 in listBox2.Items)
{
string item;
string umbenannt;
File.Copy(#ParentDirectory + "\\" + listboxitem2.ToString(), #ParentDirectory + "\\");
//listBox1.Items.Add(f.Name.Substring(0,f.Name.IndexOf("-")));
}
}
}
I guess you have a List<FileInfo> containing your files? If so you can go with File.Copy like this:
void Button2Click(object sender, EventArgs e)
{
DirectoryInfo ParentDirectory = new DirectoryInfo(#"C:\Users\A7024985\Desktop\");
string interpret = f.Name.Substring(0, f.Name.IndexOf("-")).TrimEnd(' ');
string title = f.Name.Remove(0, interpret.Length+1).TrimStart(' ');
File.Copy(f.FullName, ParentDirectory
+ interpret
+ "\\"
+ title); //or f.Name
}
Copy("C:\Users\A7024985\Desktop\Nirvana-Teen Spirit.mp3" , C:\Users\A7024985\Desktop\Nirvana\Teen Spirit.mp3
A good way to do this is use the TagLib# library (see example here) to find the ID3 tags (Artist, Song, Album, etc...), and then create a collection of these, and then sort them, and then move them to a new folder based on the Artist.
var songList = new List<string>(); //Contains a list of song files. E.g. "Come As You Are.mp3", "Heart Shaped Box.mp3", "Smells Like Teen Spirit.mp3".
var tagLibFiles = new List<TagLib.File>();
tagLibFiles.AddRange(songList.Select(x => new TagLib.File(x));
var nirvanaSongs = tagLibFiles.Where(x => x.Tag.FirstAlbumArtist == "Nirvana").ToList();
foreach(var song in nirvanaSongs)
{
//Move the file to your Nirvana folder.
}
I am guessing listboxitem.ToString() contains the name of the artist.
Then:
var filestomove = ParentDirectory.GetFiles().Where(f=>f.Name.Contains(listboxitem.ToString()));
foreach(var file in filestomove){
File.Move(file.FullName,pfas+file.Nmae)
}

C#: Unable to assign Image to PictureBox image source path from text file in winforms

I'm trying to display image in a PictureBox dynamically. Image source is stored in a text file. When reading the image path from the file it keep showing image error symbol. When I include the path in the code it works.
Text file line sample
F01,Nasi Lemak,RM 2,#"Food\NasiLemak.jpg"
public void readData()
{
try
{
int i = 0;
foreach (string line in File.ReadAllLines("food.txt"))
{
string[] parts = line.Split(',');
foreach (string part in parts)
{
Console.WriteLine("{0}:{1}", i, part);
{
Label LblFId = new Label();
{
//LblFId.AutoSize = true;
LblFId.Size = new System.Drawing.Size(70, 20);
}
Label LblFName = new Label();
{
LblFName.Size = new System.Drawing.Size(70, 20);
}
Label LblFPrice = new Label();
{
LblFPrice.Size = new System.Drawing.Size(70, 20);
}
PictureBox foodPicBox = new PictureBox();
{
foodPicBox.Size = new System.Drawing.Size(200, 200);
foodPicBox.SizeMode = PictureBoxSizeMode.StretchImage;
foodPicBox.BorderStyle = BorderStyle.Fixed3D;
}
Panel fPanel = new Panel();
LblFId.Text = parts[0];
LblFName.Text = parts[1];
LblFPrice.Text = parts[2];
foodPicBox.ImageLocation = parts[3];
fPanel.Controls.Add(LblFId);
fPanel.Controls.Add(LblFName);
fPanel.Controls.Add(LblFPrice);
fPanel.Controls.Add(foodPicBox);
foodFlow.Controls.Add(fPanel);
}
}
i++;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
The problem is in the path from the text file
#"Food\NasiLemak.jpg"
This should be saved like without the # and the "
Food\NasiLemak.jpg
Or you should write more code to remove those symbols like this
foodPicBox.ImageLocation = parts[3].Replace("#", "").Replace("\"", "");
This will remove the samples and your problem would be solved.
You need also to close foreach statment at this point
foreach (string part in parts)
{Console.WriteLine("{0}:{1}", i, part);}

How to get icon image

I want to make same Window File explorer.
but I don't know how to get file default Icon image.
If I can get file default image(Icon), I would like to add to the listview.
my code is as below
private void AddFiles(string strPath)
{
lv_local.BeginUpdate();
lv_local.Items.Clear();
iFiles = 0;
try
{
DirectoryInfo di = new DirectoryInfo(strPath + "\\");
FileInfo[] theFiles = di.GetFiles();
foreach (FileInfo theFile in theFiles)
{
iFiles++;
ListViewItem lvItem = new ListViewItem(theFile.Name);
lvItem.SubItems.Add(String.Format("{0:N0}", theFile.Length) + "KB");
lvItem.SubItems.Add(theFile.Extension);
lvItem.SubItems.Add(theFile.LastWriteTime.ToShortDateString());
lvItem.ImageIndex = 4;
// I want to put an image that was read default image
lv_local.Items.Add(lvItem);
}
}
catch (Exception Exc)
{
}
lv_local.EndUpdate();
}
Create ImageList and add icons
var imageList = new ImageList();
imageList.Images.Add("IconKey", icon);
Assign the ImageList to ListView
listView.LargeImageList = imageList;
Assign icon for the list view item
listViewItem.ImageKey = "itemImageKey";
or listViewItem.ImageIndex = 1;

how could I show filename under the image shown in the listview

I am writing a code where I need to show several images in a listview, I can get the images shown, but how could I also show the file's name beneath the image?
Below is part of my code
string stu_name_1 = listBox4.SelectedItem.ToString();
string stu_name_2 = listBox6.SelectedItem.ToString();
string add = stu_name_1 +"/"+ stu_name_2;
Directory.CreateDirectory(add);
OpenFileDialog sf = new OpenFileDialog();
Dictionary<string, string> imageDictionary = new Dictionary<string, string>();
sf.Multiselect = true;
if (sf.ShowDialog() == DialogResult.OK)
{
string[] files = sf.FileNames;
foreach (string file in files)
{
// Use static Path methods to extract only the file name from the path.
string fileName = System.IO.Path.GetFileName(file);
string destFile = System.IO.Path.Combine(add, fileName);
Image imgToAdd = Image.FromFile(file);
imgToAdd.Tag = file;
System.IO.File.Copy(file, destFile, true);
imageList1.Images.Add(imgToAdd);
//imageDictionary.Add(Path.GetFileName(file), file);
}
}
listView1.Items.Clear();
for (int i = 0; i < imageList1.Images.Count; i++)
{
ListViewItem lvi = new ListViewItem();
lvi.ImageIndex = i;
listView1.Items.Add(lvi);
string stu_name_1 = listBox4.SelectedItem.ToString();
string stu_name_2 = listBox6.SelectedItem.ToString();
string add = stu_name_1 +"/"+ stu_name_2;
Directory.CreateDirectory(add);
OpenFileDialog sf = new OpenFileDialog();
Dictionary<string, string> imageDictionary = new Dictionary<string, string>();
sf.Multiselect = true;
if (sf.ShowDialog() == DialogResult.OK)
{
listView1.Items.Clear();//Clear first
string[] files = sf.FileNames;
foreach (string file in files)
{
// Use static Path methods to extract only the file name from the path.
string fileName = System.IO.Path.GetFileName(file);
string destFile = System.IO.Path.Combine(add, fileName);
Image imgToAdd = Image.FromFile(file);
imgToAdd.Tag = file;
System.IO.File.Copy(file, destFile, true);
imageList1.Images.Add(imgToAdd);//Suppose the imageList1 is dedicated to your listView1 only.
listView1.Items.Add(fileName, imageList1.Images.Count-1);
//imageDictionary.Add(Path.GetFileName(file), file);
}
}

Seeing duplicates in my output. Why?

The output of my app is producing duplicates of filenames...and i'm not 100% sure why that is.
My app "cleans" the file name by finding the regex pattern in the filename. If there is none, it dumps it into a "normal" list and ignores it.
Here is the code i'm using to display my output: [this keeps showing me duplicates of filenames!!]
public partial class DriveRecursion_Results : Form
{
List<string> paths = new List<string>();
public DriveRecursion_Results()
{
InitializeComponent();
}
public void DriveRecursion(string retPath)
{
string pattern = (#"[~#&!%+{}]+");
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
List<string> normal = new List<string>();
List<string> fileNameOnlyList = new List<string>();
dataGridView1.Rows.Clear();
try
{
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
foreach (string nameOnly in fileNameOnlyList)
{
if (regEx.IsMatch(strippedFileName))
{
//string fileNameOnly = Path.GetFileName(fileNames);
string pathOnly = Path.GetDirectoryName(fileNames);
DataGridViewRow dgr = new DataGridViewRow();
dgr.CreateCells(dataGridView1);
dgr.Cells[0].Value = pathOnly;
dgr.Cells[1].Value = nameOnly;
dataGridView1.Rows.Add(dgr);
string pathforInvalidName = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(nameOnly), pathOnly);
paths.Add(pathforInvalidName);
}
else
{
normal.Add(strippedFileName);
}
}
}
}
catch (Exception e)
{
StreamWriter sw = new StreamWriter(retPath + "ErrorLog.txt");
sw.Write(e);
}
}
private void button1_Click_1(object sender, EventArgs e)
{
this.Close();
CleanNames clean = new CleanNames();
clean.Sanitizer(paths);
clean.Show();
}
Once it's done identifying which files need to be renamed, it cleans up the "dirty" names:
public partial class CleanNames : Form
{
public CleanNames()
{
InitializeComponent();
}
public void Sanitizer(List<string> paths)
{
string regPattern = (#"[~#&!%+{}]+");
string replacement = " ";
Regex regExPattern = new Regex(regPattern);
Regex regExPattern2 = new Regex(#"\s{2,}");
StreamWriter errors = new StreamWriter(#"S:\Test\Errors.txt", true);
var filesCount = new Dictionary<string, int>();
dataGridView1.Rows.Clear();
try
{
foreach (string files2 in paths)
{
string filenameOnly = System.IO.Path.GetFileName(files2);
string pathOnly = System.IO.Path.GetDirectoryName(files2);
string sanitizedFileName = regExPattern.Replace(filenameOnly, replacement);
sanitizedFileName = regExPattern2.Replace(sanitizedFileName, replacement);
string sanitized = System.IO.Path.Combine(pathOnly, sanitizedFileName);
if (!System.IO.File.Exists(sanitizedFileName))
{
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = filenameOnly;
clean.Cells[2].Value = sanitizedFileName;
dataGridView1.Rows.Add(clean);
System.IO.File.Move(files2, sanitized);
}
else
{
if (filesCount.ContainsKey(sanitizedFileName))
{
filesCount[sanitized]++;
}
else
{
filesCount.Add(sanitized, 1);
}
string newFileName = String.Format("{0}{1}{2}",
System.IO.Path.GetFileNameWithoutExtension(sanitized),
filesCount[sanitized].ToString(),
System.IO.Path.GetExtension(sanitized));
string newFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(sanitized), newFileName);
newFileName = regExPattern2.Replace(newFileName, replacement);
System.IO.File.Move(files2, newFilePath);
sanitized = newFileName;
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = filenameOnly;
clean.Cells[2].Value = newFileName;
dataGridView1.Rows.Add(clean);
}
}
}
catch (Exception e)
{
errors.Write(e);
}
}
private void SanitizeFileNames_Load(object sender, EventArgs e)
{ }
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}
What i'm trying to do here is ONLY show files that need to be renamed (not all files). I want to take those dirty filenames and clean them with my 2nd class.
Anybody know why i'm seeing multiples of the same file on the output? Anybody know how to fix this?!?!
My immediate observation is that your foreach (string nameOnly in fileNameOnlyList) loop should not be nested where it is. Your logic looks like this.
For each filename:
Add it to the list.
For *everything in the list*...
So you'll add one. Then process it. Then add another. Then process both. Then add. Then process all three. Etcetera.
Try this.
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
}
foreach (string strippedFileName in fileNameOnlyList)
{
if (regEx.IsMatch(strippedFileName))
// ...
}
Edit
Even better, why have two loops?
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
if (regEx.IsMatch(strippedFileName))
// ...
}
My first guess is that you are seeing duplicates because you have the loop over fileNameOnlyList inside the loop over fileDrive. This when you are processing second file name from fileDrive collection, you will add the first one to your data grid as well.
There are two possible ways to fix it:
- move the inner loop out of the outer loop and put it just under it
- remove the inner loop (but leave the code that is inside it) and use strippedFileName instead of nameOnly variable in the code
You search recursively through your directory structure
Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
but you use only the filename
System.IO.Path.GetFileName(fileNames);
So if you have the same file in nested folders, it will show up twice.

Categories

Resources