Background: I'm developing a WinForms application using C# with an OpenFileDialog and FileBrowserDialog that is supposed to:
Enable selection of multiple xls files.
After selection is made, Display selected xlsx filenames in textbox
Copy the selected files to a separate directory Consolidated
Show results in logging window on the bottom of the winForm App
How do you recommend to fix any of the following Errors in Debugging:
After selecting the files from the FileBrowserDialog, another FileBrowserDialog box comes up
Only 1 of the files selected shows up in the textbox. There's not enough room to display all files b/c the file paths are so long. Would it be possible to just display the filename without the full path? Is there a better way for confirming the MultiSelect worked in a WinForm besides displaying the selected files in a textbox that you recommend?
Hitting the Consolidate button does not copy the selected files to the consolidated directory or display the correct log files.
I get the following in the Logging Window: "Source Files: System.String[]"
Here's my code:
private void sourceFiles_Click(object sender, EventArgs e)
{
Stream myStream;
int i = 0;
OpenFileDialog sourceFilesList = new OpenFileDialog();
this.sourceFileOpenFileDialog.InitialDirectory = "i:\\CommissisionReconciliation\\Review\\";
this.sourceFileOpenFileDialog.Filter = "Excel Files (*.xls;*.xlsx;)|*.xls;*.xlsx;|All Files (*.*)|*.*";
this.sourceFileOpenFileDialog.FilterIndex = 2;
this.sourceFileOpenFileDialog.RestoreDirectory = true;
this.sourceFileOpenFileDialog.Multiselect = true;
this.sourceFileOpenFileDialog.Title = "Please Select Excel Source File(s) for Consolidation";
if (sourceFileOpenFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
if ((myStream = sourceFileOpenFileDialog.OpenFile()) != null)
{
using (myStream)
{
Log("Source Files: " + sourceFilesList.FileNames);
}
} // ends if
} // ends try
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
} // ends if (sourceFileOpenFileDialog.ShowDialog() == DialogResult.OK)
} // ends public void sourceFiles_Click
private void consolidateButton_Execute_Click(object sender, EventArgs e)
{
string consolidatedFolder = targetFolderBrowserDialog.SelectedPath;
foreach (String file in sourceFileOpenFileDialog.FileNames)
{
try
{
// Copy each selected xlsx files into the specified TargetFolder
System.IO.File.Copy(sourceFileOpenFileDialog.FileName, consolidatedFolder + #"\" + System.IO.Path.GetFileName(sourceFileOpenFileDialog.FileName));
Log("File" + sourceFileOpenFileDialog.FileName + " has been copied to " + consolidatedFolder + #"\" + System.IO.Path.GetFileName(sourceFileOpenFileDialog.FileName));
}
} // ends foreach loop
} // ends void consolidateButton_Execute_Click
I will give +1 up-votes for any helpful answers!
Thanks for looking!
Update: Updated code w/ a foreach (string FileName in sourceFilesList.FileNames) loop and a listbox control, still having problems w/ filebrowser loading 2x, and the "Source Files: System.String[]" message
Your code snippet doesn't match your question very well, there's no sign of you displaying the FolderBrowserDialog. There is an obvious mistake in the File.Copy() call, you pass sourceFileOpenFileDialog.FileName instead of file.
Check this answer for a way to display path names in a limited amount of space:
using System;
using System.ComponentModel;
using System.Windows.Forms;
class PathLabel : Label
{
[Browsable(false)]
public override bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = false; }
}
protected override void OnPaint(PaintEventArgs e)
{
TextFormatFlags flags = TextFormatFlags.Left | TextFormatFlags.PathEllipsis;
TextRenderer.DrawText(e.Graphics, this.Text, this.Font, this.ClientRectangle, this.ForeColor, flags);
}
}
To get only file name from file path use Path.GetFileName(...).
To check if multiple files were selected, you can just check openFileDialog.FileNames Length property - it's an array.
Fixed Logging Window Message: "Source Files: System.String[]" by adding:
foreach (string FileName in sourceFilesList.FileNames)
{
sourceFilesList.FileNames[i] = FileName;
listBoxSourceFiles.Items.Add(FileName);
Log("Source Files: " + sourceFilesList.FileNames[i]);
i++;
}
// under if ((myStream = sourceFileOpenFileDialog.OpenFile()) != null)
Fixed 2 FileBrowserDialog boxes coming up when Selecting files by:
if ((myStream = sourceFilesList.OpenFile()) != null)
// deleted duplicate line
Related
I am working on this piece of code that is supposed to open a file dialog and put them into a textbox.
The error is that every time I select more than 1 file while running the app, I get an error in the textbox. If I select only one file, it works fine.
The code is this
private void filePickerButton_Click(object sender, RoutedEventArgs e)
{
// Create the OpenFileDialog object
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = "C:\\Users";
dialog.Multiselect = true;
// Check to see if we have a result
if (dialog.ShowDialog() == true)
{
filePickerTextBox.Text = dialog.FileNames.ToString();
}
else
{
outputTextBox.Text = "Operation cancelled." + "\n" + outputTextBox.Text;
}
}
I am switching between dialog.Filename.ToString(); (to select one file) and dialog.Filenames.ToString(); to select multiple. When using the latter and selecting a file (whether its only one, or more that one, doesn't matter) the my text box shows System.String[]
Anyone know how to fix this?
Thx!
when you are selecting multiple files you get a array of files, as your textbox says: System.String[]
you could use:
filePickerTextBox.Text = string.join(",", dialog.FileNames);
I'm trying to load files from a folder and listing them in the ListBox control. After that, once the user selects (double clicks) any list item(file), then it should open in the RichTextBox control.
I have tried an implementation at my end, provided below
public void DisplayFolder(string folderPath)
{
listView1.Clear();
listView1.Columns.Add("File Name", 150);
listView1.Columns.Add("Last Accessed", 110);
listView1.Columns.Add("Size", 80);
listView1.Activation = ItemActivation.TwoClick;
listView1.View = View.Details;
string[] files = System.IO.Directory.GetFiles(folderPath);
foreach (string file in files)
{
string fileName = Path.GetFileNameWithoutExtension(file);
ListViewItem item = new ListViewItem(new[] {fileName, File.GetLastAccessTime(file).ToString(), file.Length.ToString()});
listView1.Items.Add(item);
}
}
private void listView1_ItemActivate(object sender, EventArgs e)
{
RichTextBox rct = (RichTextBox)((Control)sender).TopLevelControl.Controls[1];
string filepath = listView1.SelectedItems.ToString();
string fileName = listView1.FocusedItem.Text;
rct.LoadFile(filepath + "\\" + fileName);
}
The file selected in the ListBox control should get loaded in the RichTextBox control.
Exception is:
File not found exception error occurs on rct.LoadFile(filepath + "\" + fileName); code line.
The line string filepath = listView1.SelectedItems.ToString(); will not work the way you are expecting it to. listView1.SelectedItems is a collection and not an individual item that points to a filepath. In addition, you are not storing the filepath anywhere in the listview.
I suggest you add the file path as per:
ListViewItem item = new ListViewItem(new[] {fileName, File.GetLastAccessTime(file).ToString(), file.Length.ToString(), folderPath});
This will add the folderPath to the last item in the ListView, where you can reference it later on.
Also, modifying your _ItemActivate handler to be as below, will get the filePath from the ListView:
string filepath = listView1.FocusedItem.SubItems[3].Text;
Finally, when loading the file, you should make use of Path.Combine instead of concatenating strings, for example:
rct.LoadFile(Path.Combine(filepath, fileName));
I'm doing a text editor. How do I display a list of the last opened files in the RichTextBox in ListView? You can also click on the ListView string and open the file. Something like the history of opening files. Files are opened using Button (the code below).
private void buttonOpen_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Rich Text Format | *.rtf";
if (ofd.ShowDialog() == DialogResult.OK)
{
richTextBox1.LoadFile(ofd.FileName);
}
else
{
}
}
The easiest way i have done this was store all opened files within a settings string and store all recently opened files within that string with a delimiter like \n(i use this because you cant include it in a fie name so no errors are thrown).
For example, the settings string is stored like this
"C:\my file1\nC:\myFile2\nC:\my file 3"
And when adding a new file to the list
MyApp.Properties.Settings.recents = MyApp.Properties.Settings.recents + "\n" + ofd.FileName;
MyApp.Properties.Settings.Default.Save();
you then split that and use a forloop for each occurance to generate a new listview item like this
string[] recentFiles = MyApp.Properties.Settings.recents.split('\n');
foreach (string recentItem in recentFiles) { MyListView.add(recentItem); }
I new to programming and C# and seemed to have worked myself into a bit muddle with the above.
What i am trying to do is create a front end for the living room media pc nothing to fancy to start with as i understand this is a mamoth task for a total noobie like me.
Ive flapped about and am totally fine with launching external exe's,storing/loading resouces ect.. and been very happy with my results for my 2 week surfing.
So im starting off my project by just launching an emulator to start with and what i would like to do is scan a folder for zip files and image files and if it finds matching image and zip files it displays an image in a list view for each zip found.
So i populate my listboxes like this and get my 2 listboxes showing the stuff i want to see.
PopulateListBox(listBox1, "\\SomePath\\", "*.zip");
PopulateListBox(listBox2, "\\Images\\", "*.jpg");
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);
}
}
So i now have my 2 listboxes and can see i have game1.zip and game1.jpg, great now i can populate my listview with the game1 image and launch the emulator he say's simple.
This is how i am currently populating the listview.
PopulateListView();
private void PopulateListView()
{
if (listBox1.Items.Contains("game1.zip"))
{
if (File.Exists("\\Images\\game1.jpg"))
{
imageList1.Images.Add(Image.FromFile("\\Images\\game1.jpg"));
listView1.Items.Add("", 0);
}
}
if (listBox1.Items.Contains("game2.zip"))
{
if (File.Exists("\\Images\\game2.jpg"))
{
imageList1.Images.Add(Image.FromFile("\\Images\\game2.jpg"));
listView1.Items.Add("", 1);
}
}
}
This is how i am currently launching and it works ok.
// launch item
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (listView1.Items[0].Selected == true)
{
string rom = "\\" + listBox1.Items[0].ToString();
// Launch code in here
}
if (listView1.Items[1].Selected == true)
{
string rom = "\\" + listBox1.Items[1].ToString();
// Launch code in here
}
}
So what the problem you may ask ?
Instead of keep typing in all that info for each item i want to use some kind of statment if possible and i dont know what to search for which does not help.
The image name will allways match the zip name just need to loose the file extensions so to populate the listview somthing like this.
if (listbox1 item = listbox2 item)
{
add to imagelist and listview automaticly with same index
}
Then i want to be able to launch just using somthing like this.
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
string rom = "\\" + listview.selected.item.tostring;
// Launch code in here
}
Hope im making sense im at my witts end.
Regards
Derek
If i understand correctly, you want to read, match and show programmatically all images and zips that are the same and when the user clicks a list view row to start the rom. This can be done as follows:
read all images - there is no need to check if the file exists, because if it does not, then GetFiles will not find it!
read all roms - same as above!
take all names that have both image and zip file (that are the same)
fill image list and list view at the same time
bind list view item with the correct image
store rom location
handle mouse click on row and fetch rom location
do something with rom file
The code:
public ListForm()
{
InitializeComponent();
// path to images and roms
const string location = #"d:\temp\roms\";
// bind image list with list view
listViewControl.SmallImageList = imageList;
// get all images without extension
var images = System.IO.Directory.GetFiles(location, "*.gif").Select(f => System.IO.Path.GetFileNameWithoutExtension(f)).ToList();
// get all roms without extension
var zips = System.IO.Directory.GetFiles(location, "*.zip").Select(f => System.IO.Path.GetFileNameWithoutExtension(f)).ToList();
// find all entries (images and zips) that have the same name
var matching = images.Intersect(zips);
var imageIndex = 0;
// fill image list and list view at the same time and store rom location
foreach (var match in matching)
{
// path to file without extension
var file = System.IO.Path.Combine(location, match);
// add image to image list
imageList.Images.Add(match, Bitmap.FromFile(string.Format("{0}.gif", file)));
// create list view item
var lvi = new ListViewItem(match);
// and set list view item image
lvi.ImageIndex = imageIndex;
// store rom location
lvi.Tag = string.Format("{0}.zip", file);
imageIndex++;
// and show
listViewControl.Items.Add(lvi);
}
}
private void listViewControl_MouseClick(object sender, MouseEventArgs e)
{
// when user clicks an item, fetch the rom location and go
var item = listViewControl.GetItemAt(e.X, e.Y);
if (item != null)
{
var pathToRom = item.Tag as string;
// do something with rom ...
}
}
There is no need to handle the image list and the list view separately. The output looks like:
you can Populate the images using the names from the listView:
private void PopulateListView()
{
foreach (string curr in listBox1.Items)
{
string changed = "\\Images\\" + curr.Replace(".zip", ".jpg");
if (File.Exists(changed))
{
imageList1.Images.Add(Image.FromFile(changed));
listView1.Items.Add("", 1);
}
}
}
and use the selected item in the MouseDoubleClick event
// launch item
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
string selected = (string) listBox1.SelectedItem;
string rom = "\\" + selected;
// Launch code in here
}
If I'm understanding your problem correctly, you can switch out your tower of if statements with this:
var item = listView1.SelectedItem
string rom = "\\" + item.ToString()
// Launch code in here
And to populate it, you can change this:
if (listBox1.Items.Contains("game2.zip"))
{
if (File.Exists("\\Images\\game2.jpg"))
{
imageList1.Images.Add(Image.FromFile("\\Images\\game2.jpg"));
listView1.Items.Add("", 1);
}
}
To this:
List<string> files = new List<string> { "game1.zip", "game2.zip" };
var index = 0;
foreach (var file in files)
{
if (File.Exists("\\Images\\" + file))
{
imageList1.Images.Add(Image.FromFile("\\Images\\" + file.Replace(".zip", ".jpg")));
listView1.Items.Add("", index);
index++;
}
}
Here is the application on codeplex all i did is created a new text box and trying to get path of current node selected into this text box, but i am getting extra things which i dont need at all,
Link to application,
Codeplex app
Code Line i am using is ,
TextBox1.Text = nodeCurrent.FullPath;
and output i am getting is something like this,
My Computer\C:\\Documents and Settings\Administrator\Desktop
My Computer here is Root Node, which i dont need, all i want is
C:\Documents and Settings\Administrator\Desktop
Picture added
Here is the function i am using it
private void tvFolders_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
{
//Populate folders and files when a folder is selected
this.Cursor = Cursors.WaitCursor;
//get current selected drive or folder
TreeNode nodeCurrent = e.Node;
string newPath = getFullPath(nodeCurrent.FullPath);
tbDirectory.Text = newPath;
//clear all sub-folders
nodeCurrent.Nodes.Clear();
if (nodeCurrent.SelectedImageIndex == 0)
{
//Selected My Computer - repopulate drive list
PopulateDriveList();
}
else
{
//populate sub-folders and folder files
PopulateDirectory(nodeCurrent, nodeCurrent.Nodes);
}
this.Cursor = Cursors.Default;
}
It looks to me like the getFullPath method in that code will do exactly what you want. It strips the MyComputer\ string and returns the rest. Write:
string newPath = getFullPath(nodeCurrent.FullPath);
add the following line in the code and it will remove recurring "\" in the path
newPath = newPath.Replace("\\\\", "\\");