I have a windows form that contains two controls (TreeView and ListView), i want to display all directories for a specific path in the TreeView and when the user clicks to any directory listed in the TreeView all the files of this directory shown in the ListView.
That is my code:
In Form_Load event handler i loaded all the directory from E Drive to the treeView1
private void Form1_Load(object sender, EventArgs e)
{
DirectoryInfo dInfo = new DirectoryInfo(#"E:\");
foreach (DirectoryInfo d in dInfo.GetDirectories())
{
treeView1.Nodes[0].Nodes.Add(d.Name);
}
}
Here is the problem:
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
try
{
DirectoryInfo dInfo = new DirectoryInfo(e.Node.Text);
foreach (FileInfo f in dInfo.GetFiles())
{
listView1.Items.Add(f.Name);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.Source);
}
}
When any body click on any directory in the treeView1 the code jump to the catch insted of listing all files in the listView1.
The Exception Message: Couldn't find a part of the path.
You need to add some data to the tree node. You can either put the full path name in the Text, by changing your code to:
treeView1.Nodes[0].Nodes.Add(d.FullName);
Or, you can use the Name, and add some extra data to the Tag field of the TreeNode.
var node = treeView1.Nodes[0].Nodes.Add(d.Name);
node.Tag = d;
Then, when you want the files for that directory, you write:
DirectoryInfo dInfo = (DirectoryInfo)e.Node.Tag;
foreach (FileInfo f in dInfo.GetFiles())
...
If you don't want to keep all of those DirectoryInfo references around, you can put the FullName in the Tag field:
node.Tag = d.FullName;
And then when you go to retrieve the files:
DirectoryInfo dInfo = new DirectoryInfo((string)e.Node.Tag);
Related
I am attempting to have ListView in my WPF application, which accepts drag and drop - both files and directories, but in case of directories it is supposed to get files from them, not them themselves.
My XAML:
<ListView ... AllowDrop="True" Drop="importListView_Drop">
...
</ListView>
My code behind:
private void importListView_Drop(object sender, DragEventArgs e)
{
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
core.AddIntoImport(files);
}
This now produces outputs including directories and omitting files in them, f.e.
C:/Example/Files/MyFile.mp3
C:/Example/Files/SubDirectory/
...
While I'd like it to actually get all files from SubDirectory and not include SubDirectory itself. I could do this by myself: "is directory? - yes: exclude it and get all files from it instead" but the question is, is there some nicer way included in f.e. event args already?
Just to make myself more clear, following code does the job perfectly in WinForms app. Is there an alternative in WPF?
private void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
InsertImport(files);
}
private void Form1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
}
You could use this
var allFiles = files.Where(Directory.Exists)
.SelectMany(dir => Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories))
.ToList();
Just be aware, this is will throw if you have don't have appropriate permissions on the sub directories. in such case you will have to do this more manually, and check-for / ignore errors
Managed to do this in this way in the end btw...:
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
var importList = new List<string>();
foreach (string s in files)
{
if (Directory.Exists(s))
foreach (var f in Directory.GetFiles(s, "*.*", SearchOption.AllDirectories))
importList.Add(f);
else if (File.Exists(s))
importList.Add(s);
}
I am making a program in which users can modify remote files. I put the selected files (depending on some predefined criteria) in a listView, but I display only the file names, not full filepaths.
The problem I get however, is that when a user would double-click on an item, it should open another window to modify that item.
private void listView1_DoubleClick(object sender, EventArgs e)
{
account = File.ReadAllLines("\\\\myremoteserver\\ftp\\"+listView1.SelectedItems[0].Text+".txt");
Form3 passForm = new Form3();
passForm.ShowDialog();
}
private void Form2_Load(object sender, EventArgs e)
{
string[] files = Directory.GetFiles("\\\\myremotserver\\ftp\\","*.txt", System.IO.SearchOption.AllDirectories);
foreach (string s in files)
{
listView1.Items.Add(Path.GetFileNameWithoutExtension(s));
}
}
The problem is, that the files are all in different subfolders, so if I leave the code as is, it will not display the correct content of the file. For example, the file is called test1.txt, it is placed in myremoteserver\ftp\testfolder\test1.txt, but with my program, it will try to find the file in myremoteserver\ftp\test1.txt.
What I am asking is, if it is possible to modify the listView in such a way, that the full file path is always saved, but only the file names are displayed? I do not want the user to see the complete file path of the files, just the file names.
Use the Tag property of the ListViewItem
So to create items...
foreach (string s in files)
{
ListViewItem lvi = new ListViewItem(Path.GetFileNameWithoutExtension(s));
lvi.Tag = s;
listView1.Items.Add(lvi);
}
Then in event handler...
account = File.ReadAllLines("\\\\myremoteserver\\ftp\\"+listView1.SelectedItems[0].Tag +".txt);
I'm getting an unhandled exception of type System.IO.IOException occurring in mscorlib.dll because the file I'm trying to delete is being used by another process.
I want it to skip the used files.
private void button1_Click(object sender, EventArgs e)
{
System.IO.DirectoryInfo directory =
new System.IO.DirectoryInfo(#"C:\Users\fatih\AppData\Local\Temp");
foreach (System.IO.FileInfo file in directory.GetFiles()) file.Delete();
foreach (System.IO.DirectoryInfo subDirectory in directory.GetDirectories())
subDirectory.Delete(true);
}
If it's not important that you delete everything, use:
private void button1_Click(object sender, EventArgs e)
{
string directory = #"C:\Users\fatih\AppData\Local\Temp";
deleteDirectory(directory);
}
private void deleteDirectory(string directory){
foreach (string file in Directory.GetFiles(directory))
{
try{
File.Delete(file);
}
catch(Exception e0){
Console.WriteLine(e0.Message+"\n"+e0.Source);//not necessary but nice to learn from
}
}
foreach (string direc in Directory.GetDirectories(directory)) {
deleteDirectory(direc);
Directory.Delete(direc,true);
}
}
This will simply skip over any file or directory that has a problem and delete everything else.
Use the static versions of the directory and file methods, you cannot use a foreach on file.delete the way you are doing it because you are trying to do a delete operation on the thing you are looping through.
foreach (var file in Directory.GetFiles(directory))
{
File.Delete(file);
}
Update: I did not notice the subdirectory delete, that is your issue, if you want to just delete everything including the directory you are on, then you are working too hard.
Directory.Delete(Directory, true);
Will wipe out the directory and all the subdirectories and files in the directory passed in.
Since you are still having issues, and everyone seems to think I am wrong here, I will give you the code to past into your solution.
private void button1_Click(object sender, EventArgs e)
{
string directory = #"C:\Users\fatih\AppData\Local\Temp")
Directory.Delete(directory, true);
}
IF there is an outside process hanging on to the file this will not work, otherwise it will do what you want it to do
I'm a newbie in C# and I have 2 Listboxes l-->istBox1 and listBox2 and I want to load files from folder into these listboxes.
I tried like this :
listBox1:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
DirectoryInfo dinfo = new DirectoryInfo(#"C:\TestLoadFiles");
FileInfo[] Files = dinfo.GetFiles("*.rtdl");
foreach (FileInfo file in Files)
{
listbox1.Items.Add(file.Name);
}
}
listBox2:
private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
{
DirectoryInfo dinfo = new DirectoryInfo(#"C:\TestLoadFiles");
FileInfo[] Files = dinfo.GetFiles("*.dlz");
foreach (FileInfo file in Files)
{
listbox2.Items.Add(file.Name);
}
}
when i run the form, the files from the folder is not displaying???
Instead of listBox1_SelectedIndexChanged, update the listbox against some button click, otherwise your code looks fine. Initially you probably don't have any item in your listbox and that's why SelectedIndexChanged doesn't get fired when you click on it.
Edit: (Since the question has been edited, I will update my answer)
To pouplate your listboxes with Files, you should do that, in some event other than SelectedIndexChanged. Because at the start of your application your listboxes are empty and SelectedIndexChanged event gets fired when there are items in the listbox and user click on it. You may create the following function
private void PopulateListBox(ListBox lsb, string Folder, string FileType)
{
DirectoryInfo dinfo = new DirectoryInfo(Folder);
FileInfo[] Files = dinfo.GetFiles(FileType);
foreach (FileInfo file in Files)
{
lsb.Items.Add(file.Name);
}
}
Now you may call this function with your listbox in some event against a button click or form load. e.g.
private void Form1_Load(object sender, EventArgs e)
{
PopulateListBox(listbox1, #"C:\TestLoadFiles", "*.rtld");
PopulateListBox(listbox2, #"C:\TestLoadFiles", "*.other");
}
This might work ;)
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
DirectoryInfo dinfo = new DirectoryInfo(#"C:\TestLoadFiles");
FileInfo[] Files = dinfo.GetFiles("*.rtdl");
foreach (FileInfo file in Files)
{
listbox2.Items.Add(file.Name);
}
}
Wrong event i suppose. Move that code to the constructor of your form/control or attach it to an event of another control. Repopulating the listBox on SelectedIndexChanged when the initial state of the listbox is empty does not make sense.
I'm not sure whether this topics has been disscussed before or not, but I'm not sure the exact word to search for it. What method/class should I use?
The program has 3 buttons: 1) for folder browsing, 2) scan for the selected folder content, and 3) open the file. When user browse the selected folder**(1), user click scan button to scan from the first file until the last available files and listed it text box(2)** and from that user can decide whether to open the files or not**(3)**.
Here are what have I done so far (no 1 and 3):
//For browse.
private void browse2()
{
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
this.txtDest.Text = folderBrowserDialog1.SelectedPath;
}
}
//For opening folder.
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
Process.Start(txtDest.Text);
}
catch
{
MessageBox.Show("Please select one file/folder");
}
}
If you are trying to just open a file you can directly use an Open File Dialog.
If you need to display the contents of a directory you can use the Directory Info Class.
Well my example is a WPF app that adds files/ folders in a directory to a treeview, but you should get the general idea:
Note: Code was written for a training exercise, and therefore only goes 3 levels deep, as a proof of concept kind of thing
private void Window_Loaded(object sender, RoutedEventArgs e)
{
foreach (DriveInfo di in DriveInfo.GetDrives())
{
TreeViewItem drive = new TreeViewItem();
drive.Header = di.Name;
treeView1.Items.Add(drive);
DirectoryInfo folders = new DirectoryInfo(di.Name);
// The depth count means that it only goes 3 levels deep, to make it quick to load
GetFoldersAndFiles(drive, folders, 3);
}
}
private static void GetFoldersAndFiles(TreeViewItem parent, DirectoryInfo folders, int depth)
{
if ((depth > 0)
{
foreach (DirectoryInfo dirI in folders.GetDirectories())
{
TreeViewItem dir = new TreeViewItem();
dir.Header = dirI.Name;
parent.Items.Add(dir);
GetFoldersAndFiles(dir, dirI, depth - 1);
}
foreach (FileInfo fileI in folders.GetFiles())
{
TreeViewItem file = new TreeViewItem();
file.Header = fileI.Name;
parent.Items.Add(file);
}
}
}