So far I have created a File Explorer - however I want to add a button which will allow the selected file to be opened when clicked. I've heard about the OpenFileDialog but it only seems to show a directory which I don't want. Any ideas? This is the code I've got, using C#.
namespace SynchronizeTaskPaneAndRibbon
{
public partial class FileChooser : UserControl
{
private void PopulateTreeView()
{
TreeNode rootNode;
DirectoryInfo info = new DirectoryInfo(#"../..");
if (info.Exists)
{
rootNode = new TreeNode(info.Name);
rootNode.Tag = info;
GetDirectories(info.GetDirectories(), rootNode);
treeView1.Nodes.Add(rootNode);
}
}
private void GetDirectories(DirectoryInfo[] subDirs, TreeNode nodeToAddTo)
{
TreeNode aNode;
DirectoryInfo[] subSubDirs;
foreach (DirectoryInfo subDir in subDirs)
{
aNode = new TreeNode(subDir.Name, 0, 0);
aNode.Tag = subDir;
aNode.ImageKey = "folder";
try
{
subSubDirs = subDir.GetDirectories();
}
catch (System.UnauthorizedAccessException)
{
subSubDirs = new DirectoryInfo[0];
}
if (subSubDirs.Length != 0)
{
GetDirectories(subSubDirs, aNode);
}
nodeToAddTo.Nodes.Add(aNode);
}
}
public FileChooser()
{
InitializeComponent();
PopulateTreeView();
this.treeView1.NodeMouseClick += new TreeNodeMouseClickEventHandler(this.treeView1_NodeMouseClick);
}
void treeView1_NodeMouseClick(object sender,TreeNodeMouseClickEventArgs e)
{
TreeNode newSelected = e.Node;
listView1.Items.Clear();
DirectoryInfo nodeDirInfo = (DirectoryInfo)newSelected.Tag;
ListViewItem.ListViewSubItem[] subItems;
ListViewItem item = null;
foreach (DirectoryInfo dir in nodeDirInfo.GetDirectories())
{
item = new ListViewItem(dir.Name, 0);
subItems = new ListViewItem.ListViewSubItem[]
{new ListViewItem.ListViewSubItem(item, "Directory"),
new ListViewItem.ListViewSubItem(item,
dir.LastAccessTime.ToShortDateString())};
item.SubItems.AddRange(subItems);
}
foreach (FileInfo file in nodeDirInfo.GetFiles())
{
if (file.Extension == ".xlsx" || file.Extension == ".xls" || file.Extension == ".xlsm" || file.Extension == ".csv")
{
item = new ListViewItem(file.Name, 1);
subItems = new ListViewItem.ListViewSubItem[]
{ new ListViewItem.ListViewSubItem(item, "File"),
new ListViewItem.ListViewSubItem(item,
file.LastAccessTime.ToShortDateString())};
item.SubItems.AddRange(subItems);
listView1.Items.Add(item);
}
}
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
First, when creating the ListViewItems, I'd add the full path of the file to the .Tag so you can retrieve it easily:
item.Tag = file.FullName;
Then you'd use something like this in a button click event:
private void button1_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
foreach(ListViewItem lvi in listView1.SelectedItems)
{
if (lvi.Tag != null && lvi.Tag is string)
{
string fullPathFile = lvi.Tag.ToString();
try
{
Process.Start(fullPathFile);
}
catch (Exception ex)
{
MessageBox.Show("FileName: " + fullPathFile + "\r\n\r\n" + ex.ToString(), "Error Opening File");
}
}
}
}
}
Related
I have a TreeView that shows all the folders on the computer.
How can I see all the files within a particular folder that in the TreeView?
try this:
private void button1_Click(object sender, EventArgs e)
{
treeView1.ShowNodeToolTips = true;
DirectoryInfo d = new DirectoryInfo("C:\\projects");
GetAllDirectories(d, null);
}
void GetAllDirectories(DirectoryInfo d, TreeNode nodeToAddChilds)
{
if (treeView1.Nodes.Count == 0)
{
TreeNode root = new TreeNode();
root.ToolTipText = GetFileNames(d);
root.Text = d.Name;
treeView1.Nodes.Add(root);
nodeToAddChilds = root;
}
DirectoryInfo[] dirList = d.GetDirectories();
foreach (DirectoryInfo oneDir in dirList)
{
if (oneDir.Name.StartsWith("$"))
{
// Just to avoid system permission limitations
continue;
}
TreeNode newChild = new TreeNode();
newChild.ToolTipText = GetFileNames(oneDir);
newChild.Text = oneDir.Name;
nodeToAddChilds.Nodes.Add(newChild);
GetAllDirectories(oneDir, newChild);
}
}
string GetFileNames(DirectoryInfo d)
{
string files = "files:\r\n";
FileInfo[] allFiles = d.GetFiles();
foreach (FileInfo oneFile in allFiles)
{
files += oneFile.Name + "\r\n";
}
return files;
}
private void treeView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
// Get the selected node.
TreeNode node = treeView1.SelectedNode;
DirectoryInfo d = new DirectoryInfo(node.text);
FileInfo[] Files = d.GetFiles();
}
I got a Form that wants to have atleast one keyword, like download.
This is the Code to call my OpenFileDialog.
The Class is Form1
public Form1()
{
InitializeComponent();
initListView();
}
private void button1_Click(object sender, EventArgs e)
{
getallfiles.getSelectedFiles(this.listView1);
}
private void initListView()
{
listView1.View = View.Details;
listView1.Columns.Add("Filename", 210, HorizontalAlignment.Left);
listView1.Columns.Add("Size", 60, HorizontalAlignment.Left);
listView1.Columns.Add("Match", 60, HorizontalAlignment.Left);
}
private void button2_Click(object sender, EventArgs e)
{
try
{
listView1.Items.Clear();
seaching.matchResult(progressBar1, listView1, textBox1.Text, textBox2.Text);
}
catch (Exception f)
{
MessageBox.Show(f.ToString());
}
}
Now I get the Multiselected Files and store them in the filePaths String[].
The Class is getallfiles
public static String[] filePaths;
public static void getSelectedFiles(ListView listView)
{
OpenFileDialog openAllFiles = new OpenFileDialog();
openAllFiles.Title = "Select all files you want to look for keywords";
openAllFiles.Multiselect = true;
openAllFiles.Filter = "(*.*)|*.*";
if (openAllFiles.ShowDialog() == DialogResult.OK)
{
filePaths = new string[openAllFiles.FileNames.Length];
int count = 0;
foreach (String file in openAllFiles.FileNames)
{
try
{
ListViewItem masterItem = new ListViewItem(new[] { Path.GetFileName(file), (Math.Round(((new FileInfo(file).Length) / 1024f), 3).ToString()) + " kb"});
listView.Items.Add(masterItem);
filePaths[count] = file;
count++;
}
catch (Exception f)
{
MessageBox.Show(f.ToString());
}
}
}
}
And now my Problemcode. I can filter if there is only the Keyword written, but if it's downloading and I set the Keyword to download my solutions stops working.
The Class is searching
public static void matchResult(ProgressBar progressBar, ListView listView, String key1, String key2)
{
progressBar.Maximum = getallfiles.filePaths.Length;
progressBar.Value = 0;
int count = 0;
bool lockCount = false;
String fileText;
foreach (string file in getallfiles.filePaths)
{
using (StreamReader reader = new StreamReader(getallfiles.filePaths[count]))
{
while ((fileText = reader.ReadLine()) != null)
{
if (String.IsNullOrEmpty(key2) & !String.IsNullOrEmpty(key1))
{
if (fileText.Contains(key1.ToLower()) | fileText.Contains(key1.ToUpper()) | fileText.Contains(key1))
{
ListViewItem masterItem = new ListViewItem(new[] { Path.GetFileName(file), (Math.Round(((new FileInfo(file).Length) / 1024f), 3).ToString()) + " kb" });
listView.Items.Add(masterItem);
count++;
lockCount = true;
reader.Close();
break;
}
}
else if(!String.IsNullOrEmpty(key2))
{
if (fileText.Contains(key1.ToLower()) | fileText.Contains(key2.ToLower()) | fileText.Contains(key1.ToUpper()) | fileText.Contains(key2.ToUpper()) | fileText.Contains(key1) | fileText.Contains(key2))
{
ListViewItem masterItem = new ListViewItem(new[] { Path.GetFileName(file), (Math.Round(((new FileInfo(file).Length) / 1024f), 3).ToString()) + " kb" });
listView.Items.Add(masterItem);
count++;
lockCount = true;
reader.Close();
break;
}
}
}
if (!lockCount)
{
count++;
}
}
}
}
My next Idea was to check for a Char[] but I'm not sure if this is efficient.
I'd let read char for char and store the current line in a char[] and compare if the char[] I'm looking for is in there.
I'm able to save the textbox text and the listview items to a txt file properly by using:
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
if (saveFileDialog1.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
{
using (StreamWriter writer = new StreamWriter(saveFileDialog1.FileName))
{
//writer.WriteLine(accountText.Text);
writer.WriteLine(accountText.Text);
if (transactionList.Items.Count > 0)
{
foreach (ListViewItem item in transactionList.Items)
{
StringBuilder newString = new StringBuilder();
foreach (ListViewItem.ListViewSubItem listSub in item.SubItems)
{
newString.Append(string.Format("{0}\t", listSub.Text));
}
writer.WriteLine(newString.ToString());
}
writer.WriteLine();
}
}
}
}
However, I'm only able to load the textbox and can't seem to get the listview to populate. Here's what I have for that so far:
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
{
using (StreamReader reader = new StreamReader(openFileDialog1.FileName))
{
accountText.Text = reader.ReadLine();
if (transactionList.Items.Count == 0)
{
foreach (ListViewItem item in transactionList.Items)
{
StringBuilder myString = new StringBuilder();
foreach (ListViewItem.ListViewSubItem listSub in item.SubItems)
{
myString.Append(string.Format("{0}\t", listSub.Text));
}
reader.Read();
}
reader.ReadToEnd();
}
}
}
}
Any tips would be appreciated.
You just need to split string by '\t' character, it will return string[]. Then just add these array items to listview.
string[] items = reader.ReadLine().Split('\t');
foreach (var item in items)
{
var listViewItem = new ListViewItem(item);
transactionList.Items.Add(listViewItem);
}
As far as I can tell you're not putting the string into the ListView.
You will want to to do something like this:
foreach (ListViewItem.ListViewSubItem listSub in item.SubItems)
{
myString.Append(string.Format("{0}\t", listSub.Text));
listSub.Text = myString.ToString();
}
You need to reverse all your actions while reading
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
{
using (StreamReader reader = new StreamReader(openFileDialog1.FileName))
{
accountText.Text = reader.ReadLine();
while(!reader.EndOfStream)
{
var myString = reader.ReadLine();
var subitems = myString.Split("\t");
// Create ListItem and assign subItems here...
transactionList.Items.Add(new ListviewItem(subitems));
}
}
}
}
}
When adding files to the listView1 in this method i do have the property Items.
private void AddFiles(string strPath)
{
listView1.BeginUpdate();
listView1.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(theFile.Length.ToString());
lvItem.SubItems.Add(theFile.LastWriteTime.ToShortDateString());
lvItem.SubItems.Add(theFile.LastWriteTime.ToShortTimeString());
listView1.Items.Add(lvItem);
}
}
catch(Exception Exc) { statusBar1.Text = Exc.ToString(); }
listView1.EndUpdate();
}
But now i want to add properties so when i'm doing mouse right click on a file it will show a contextmenu:
private void listView1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
int index = listView1.IndexFromPoint(e.Location);
if (index != ListBox.NoMatches)
{
listJobs.SelectedIndex = index;
Job job = (Job)listJobs.Items[index];
ContextMenu cm = new ContextMenu();
AddMenuItem(cm, "Run", QueueForRun, job).Enabled = !job.Pending;
AddMenuItem(cm, "Cancel run", CancelQueueForRun, job).Enabled = (job.State == JobState.Pending || job.State == JobState.Running);
AddMenuItem(cm, "Open folder", OpenFolder, job);
cm.Show(listJobs, e.Location);
}
}
}
This time i don't have IndexFromPoint and also not Items
Because IndexFromPoint() is a ListBox method, ListView has not. In ListView there is GetItemAt() method to achieve same result.
var item = listView.GetItemAt(e.Location.X, e.Location.Y);
if (item != null) {
listJobs.SelectedIndex = item.Index; // Assuming listJobs is a ListBox
}
EDIT: according to your comment if listJobs is a ListView too then it has not SelectedIndex but it has SelectedIndices, simply:
listJobs.SelectedIndices.Clear();
listJobs.SelectedIndices.Add(item.Index);
You have first to clear the list because, by default, MultiSelect is true then you may select multiple items.
I am working in C# WinForms. I have made a Windows Explorer that displays the logical directories and then when clicked on them, it shows the files in them in a ListView (old but tricky thing). I get the icons from the system, using:
Icon iconForFile = SystemIcons.WinLogo;
ListViewItem lv = new ListViewItem(filData, imageList1.Images.Count);
lv.Tag = file;
iconForFile = Icon.ExtractAssociatedIcon(file);
string Extension = Path.GetExtension(file);
if (!imageList1.Images.ContainsKey(file))
{
// If not, add the image to the image list.
iconForFile = System.Drawing.Icon.ExtractAssociatedIcon(file);
imageList1.Images.Add(file, iconForFile);
}
lv.ImageKey = file;
listView1.SmallImageList = imageList1;
Now the problem is this: it does show the icons when a directory at first-level is clicked but when I click the folders in any directory (ie. "C"), it doesn't show the icons in the subfolders of a directory. Please help me on how I can customize it. My full code is somewhat like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
PopulateTreeView(treeView1);
}
private void PopulateTreeView(TreeView tv)
{
string[] drives = Environment.GetLogicalDrives();
TreeNode MyCnode = new TreeNode();
MyCnode = new TreeNode("My Computer");
tv.Nodes.Add(MyCnode);
foreach (string drive in drives)
{
TreeNode nodeDrive = new TreeNode();
nodeDrive.Tag = drive;
nodeDrive.Text = drive;
tv.Nodes.Add(nodeDrive);
// tv.Nodes.Add();
// nodeDrive.EnsureVisible();
// treeView1.Refresh();
try
{
//add dirs under drive
if (Directory.Exists(drive))
{
foreach (string dir in Directory.GetDirectories(drive))
{
TreeNode node = new TreeNode();
node.Tag = dir;
node.Text = dir.Substring(dir.LastIndexOf(#"\") + 1);
node.ImageIndex = 1;
nodeDrive.Nodes.Add(node);
}
}
}
catch (Exception)
{
}
MyCnode.Expand();
}
}
public TreeNode GetDirectory(TreeNode parentNode)
{
DirectoryInfo d = new DirectoryInfo(parentNode.FullPath);
DirectoryInfo[] dInfo = d.GetDirectories()
.Where(di => !di.Attributes.HasFlag(FileAttributes.System))
.Where(di => !di.Attributes.HasFlag(FileAttributes.Hidden))
.ToArray();
parentNode.Nodes.Clear();
if (dInfo.Length > 0)
{
TreeNode treeNode = new TreeNode();
foreach (DirectoryInfo driSub in dInfo)
{
treeNode = parentNode.Nodes.Add(driSub.Name);
treeNode.Nodes.Add("");
}
}
return parentNode;
}
private void AddFiles(string strPath)
{
try
{
listView1.BeginUpdate();
listView1.Items.Clear();
//headers listview
// listView1.Columns.Add("File Name", 200);
//listView1.Columns.Add("Size", 80);
//listView1.Columns.Add("Last Accessed", 110);
string[] dirData = new string[3];
string[] filData = new string[3];
string[] files = Directory.GetFiles(strPath);
foreach (string file in files)
{
FileInfo finfo = new FileInfo(file);
FileAttributes fatr = finfo.Attributes;
string name = Path.GetFileNameWithoutExtension(file);
filData[0] = name;
filData[1] = finfo.Length.ToString();
filData[2] = File.GetLastAccessTime(file).ToString();
// Set a default icon for the file.
Icon iconForFile = SystemIcons.WinLogo;
ListViewItem lv = new ListViewItem(filData, imageList1.Images.Count);
lv.Tag = file;
iconForFile = Icon.ExtractAssociatedIcon(file);
string Extension = Path.GetExtension(file);
if (!imageList1.Images.ContainsKey(file))
{
// If not, add the image to the image list.
iconForFile = System.Drawing.Icon.ExtractAssociatedIcon(file);
imageList1.Images.Add(file, iconForFile);
}
lv.ImageKey = file;
listView1.SmallImageList = imageList1;
listView1.Items.Add(lv);
}
}
catch (Exception Exc) { MessageBox.Show(Exc.ToString()); }
listView1.EndUpdate();
}
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
string pathdoubleClicked = listView1.FocusedItem.Tag.ToString();
Process.Start(pathdoubleClicked);
}
private void treeView1_AfterExpand(object sender, TreeViewEventArgs e)
{
GetDirectory(e.Node);
treeView1.SelectedNode.Expand();
AddFiles(e.Node.FullPath.ToString());
}
}
for anyone still seeing this as an answer to a search, the assignment of the imagelist needs to be done before the items are added to the imagelist.
private void AddFiles(string strPath)
{
try
{
listView1.BeginUpdate();
listView1.Items.Clear();
listView1.SmallImageList = imageList1;