I am trying to make SaveFileDialog and FileOpenDialog enforce an extension to the file name entered by the user. I've tried using the sample proposed in question 389070 but it does not work as intended:
var dialog = new SaveFileDialog())
dialog.AddExtension = true;
dialog.DefaultExt = "foo";
dialog.Filter = "Foo Document (*.foo)|*.foo";
if (dialog.ShowDialog() == DialogResult.OK)
{
...
}
If the user types the text test in a folder where a file test.xml happens to exist, the dialog will suggest the name test.xml (whereas I really only want to see *.foo in the list). Worse: if the user selects test.xml, then I will indeed get test.xml as the output file name.
How can I make sure that SaveFileDialog really only allows the user to select a *.foo file? Or at least, that it replaces/adds the extension when the user clicks Save?
The suggested solutions (implement the FileOk event handler) only do part of the job, as I really would like to disable the Save button if the file name has the wrong extension.
In order to stay in the dialog and update the file name displayed in the text box in the FileOk handler, to reflect the new file name with the right extension, see the following related question.
You can handle the FileOk event, and cancel it if it's not the correct extension
private saveFileDialog_FileOk(object sender, CancelEventArgs e)
{
if (!saveFileDialog.FileName.EndsWith(".foo"))
{
MessageBox.Show("Please select a filename with the '.foo' extension");
e.Cancel = true;
}
}
AFAIK there's no reliable way to enforce a given file extension. It is a good practice anyway to verify the correct extension, once the dialog is closed and inform the user that he selected an invalid file if the extension doesn't match.
The nearest I've got to this is by using the FileOk event. For example:
dialog.FileOk += openFileDialog1_FileOk;
private void openFileDialog1_FileOk(object sender, System.ComponentModel.CancelEventArgs e)
{
if(!dialog.FileName.EndsWith(".foo"))
{
e.Cancel = true;
}
}
Checkout FileOK Event on MSDN.
I ran into this same issue, and I was able to control what was shown by doing the following:
with the OpenFileDialog, the first item in the filter string was the default
openFileDialog1.Filter = "Program x Files (*.pxf)|*.pxf|txt files (*.txt)|*.txt";
openFileDialog1.ShowDialog();
with the SaveFileDialog, the second item in the filter was used as the default:
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "txt files (*.txt)|*.txt|Program x Files (*.pxf)|*.pxf";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if (saveFileDialog1.FileName != null)
{
// User has typed in a filename and did not click cancel
saveFile = saveFileDialog1.FileName;
MessageBox.Show(saveFile);
saveCurrentState();
}
}
After having used these two filters with the respective fileDialogs, The expected results finally occurred. By default, when the user selects the save button and the savefiledialog shows up, the selected filetype is that of the Program X files type defined in the filter for the savefiledialog. Likewise the selected filetype for the openfiledialog is that of the Program X Files Type defined in the filter for the openfileDialog.
It would also be good to do some input validation as mentioned above in this thread. I just wanted to point out that the filters seem to be different between the two dialogs even though they both inherit the filedialog class.
//this must be ran as administrator due to the change of a registry key, but it does work...
private void doWork()
{
const string lm = "HKEY_LOCAL_MACHINE";
const string subkey = "\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete";
const string keyName = lm + subkey;
int result = (int)Microsoft.Win32.Registry.GetValue(keyName, "AutoComplete In File Dialog", -1);
MessageBox.Show(result.ToString());
if(result.ToString() == "-1")
{
//-1 means the key does not exist which means we must create one...
Microsoft.Win32.Registry.SetValue(keyName, "AutoComplete In File Dialog", 0);
OpenFileDialog ofd1 = new OpenFileDialog();
ofd1.ShowDialog();
}
if (result == 0)
{
//The Registry value is already Created and set to '0' and we dont need to do anything
}
}
Related
When I select file name "image.mgm", dialog System.Windows.Forms.SaveFileDialog surprisingly adds extension .BMP and return "image.mgm.BMP" via property FileName.
It doesn't happen for "image.png".
Several samples:
image.bmp ==> image.bmp
image.png ==> image.png
image.mgm ==> image.mgm.BMP
image.MGM ==> image.MGM
How can I fix the unexpected (for me) behavior?
Source of sample can be found on github: https://github.com/constructor-igor/TechSugar/tree/master/WinForm/FileSaveDialogIssue/FileSaveDialogIssue
UPD:
additional fact: when I add key "HKEY_CLASSES_ROOT.mgm" to registry, "file dialog" stop's to add ".BMP" to .mgm
public Form1()
{
InitializeComponent();
this.saveFileDialog.AddExtension = false;
}
private void btnOpenFile_Click(object sender, EventArgs e)
{
saveFileDialog.Title = #"Save calculated image";
saveFileDialog.FileName = "noname.tiff";
saveFileDialog.Filter = #"My Files(*.BMP;*.MGM;*.PNG)|*.BMP;*.MGM;*.PNG|All files (*.*)|*.*";
if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
{
MessageBox.Show(String.Format("File name {0}", saveFileDialog.FileName));
}
}
You have to use non-capital letters when defining file mask
saveFileDialog.Filter = #"My Files(*.BMP;*.MGM;*.PNG)|*.bmp;*.mgm;*.png|All files (*.*)|*.*";
This will work with either "1.mgm" or "1.MGM"
However, "1.mGm" and "1.MgM" won't work, could be fixed by adding "*.mGm" mask (just this one fixes both cases).
But then you still have problem with "1.Mgm".. sigh.
"*.mgm;*.mGm;*.Mgm;*.mgM;"
NB: The answer in this question is out of date.
So, I have a save dialog box:
...
SaveFileDialog sfd = new SaveFileDialog();
sfd.ShowDialog();
// SaveFileDialog.[Whatever] - Init code basically.
if (sfd.DialogResult == DialogResult.OK)
{
// Definitely do something.
Console.Print("File selected.");
}
if (sfd.DialogResult == DialogResult.Abort)
{
// Maybe the opposite of the above?
Console.Print("File selection Cancelled");
}
if ( ... ) { }
and so on.
But... SaveFileDialog.DialogResult has been replaced by events instead...
And that the only available events are SaveFileDialog.FileOK, SaveFileDialog.Disposed and SaveFileDialog.HelpRequest.
How do I trigger an event (or move to a line of code) based when the user clicked Cancel rather than completing it (Clicking Save)?
I'm looking to branch based on whether the user cancels or successfully selects the file location to save to.
Working with DialogResult is not deprecated and also those events are not something new.
To perform an action for Cancel, you can create your SaveFileDialog and configure it, you can call ShowDialog and then check the result:
var sfd= new SaveFileDialog();
//Other initializations ...
//sfd.Filter= "Text files (*.txt)|*.txt|All files (*.*)|*.*";
//sfd.DefaultExt = "txt";
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
MessageBox.Show("Save Clicked");
//ِDo something for save
}
else
{
MessageBox.Show("Cancel Clicked");
//Do something for cancel
}
You can access to selected file using FileName property, for example MessageBox.Show(sfd.FileName);
I'm still a beginner when it comes to programming and this is a small application I did following a C# tutorial.
private void viewImagesToolStripMenuItem_Click(object sender, EventArgs e)
{
string openedfile = "";
openfd.Title = "Insert a text file";
openfd.InitialDirectory = "C:";
openfd.FileName = "";
openfd.Filter = "text files|*.txt|word documents|*.doc|allfiles|*.*";
if (openfd.ShowDialog() == DialogResult.Cancel)
{
MessageBox.Show("Operation canceled");
}
if (openfd.ShowDialog() != DialogResult.Cancel)
{
openedfile = openfd.FileName;
richTextBox1.LoadFile(openedfile,RichTextBoxStreamType.PlainText);
}
While doing this I noticed that if I change the same application's code order just 2 lines-
string openedfile = "";
openedfile = openfd.FileName;
like below It will throw me an error like this when debugging - Empty path name is not legal.
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
openfd.Title = "Insert a text file";
openfd.InitialDirectory = "C:";
openfd.FileName = "";
openfd.Filter = "text files|*.txt|word documents|*.doc|allfiles|*.*";
**string openedfile = "";
openedfile = openfd.FileName;**
if (openfd.ShowDialog() == DialogResult.Cancel)
{
MessageBox.Show("Operation canceled");
}
if (openfd.ShowDialog() != DialogResult.Cancel)
{
richTextBox1.LoadFile(openedfile,RichTextBoxStreamType.PlainText);
}
Isn't there a way to understand errors in these type situations. What is the specific order of coding an application like this?
well, the idea is simple you cannot use a variable that has been not initialized.
in your case sm thing same is happening.
In your first code openedfile = openfd.FileName; is being executed after the dialouge has been shown. Thus the file name comes correctly.
But in the second openedfile = openfd.FileName; is getting initialized before the dilogue has been shown. Since there is no dialogue the name is null, hence it gives error.
Note. I have used initialized word not in tecnical manner.
The line openedfile = openfd.FileName; will not bind the two variables, it will copy the value that openfd.FileName has at this moment into openedfile.
In your second example the user has not yet selected a file at that moment, so this value is still empty (""). The value that is selected later in openfd will be ignored.
EDIT which is why you get the error Empty path name is not legal.
I'm going to go ahead and guess that the problem is the openfd.FileName call outside of the if block (and also before its retrieved), while the if block is still being exectuted the openfd is "left open" if you like, so you can retrieve its result.
When you have left, the if block, you are effectively saying you are done with this dialog, please continue.
In your code you are showing multiple dialogs with multiple calls to show dialog also, consider the following.
if (openfd.ShowDialog() == DialogResult.OK)
{
pictureBox1.Image = Image.FromFile(openfd.FileName);
}
else
{
MessageBox.Show("Operation canceled");
}
(Changed to use dialogresult.ok as this is more than likely the result you wish to receive from the dialog)
Update
With respect to your current applcation, each call to ShowDialog() is opening a new dialog. Consider it similar to
MessageBox.Show("woo");
MessageBox.Show("hoo");
in the above, when the first messagebox is closed, it will close the dialog and move onto handling the second message box (the next line of code), with your
if (openfd.ShowDialog() != DialogResult.Cancel)
Your showdialog is still in use by the if statement so it is deemed to be still in use and not disposed of straight away. When the if statement is finished with, your dialog will then be deemed to be ok to dispose
Also, the error in your application is not to do with the filename path, its trying to load in a file that has no name
I generally Prefer this:
private void viewImagesToolStripMenuItem_Click(object sender, EventArgs e)
{
DialogResult dr=openfd.ShowDialog();
if(dr==DialogResult.Ok)
{
richTextBox1.LoadFile(openfd.FileName,RichTextBoxStreamType.PlainText);
}
else
{
MessageBox.Show("No file Selected!!");
}
}
I thought using application settings would do the trick but I'm not getting it to work. This is what I have:
private void btnBrowse_Click(object sender, EventArgs e)
{
if (fbFolderBrowser.ShowDialog() == DialogResult.OK)
{
// I want to open the last folder selected by the user here.
}
When the user clicks on this button, I want to open the browse window to the last folder he accessed and save it. Next time he clicks on the button, it'll automatically select that folder.
I was thinking maybe I could use user variables where I can change at run-time but I'm not getting it to work. Can anyone give me a hand?
Go to Settings Page, Project Designer of the project which you have created and add folder path variable inside the application. Now add below code to restore the last selected folder path.
FolderBrowserDialog folderBrowser = new FolderBrowserDialog();
folderBrowser.Description = "Select a folder to extract to:";
folderBrowser.ShowNewFolderButton = true;
folderBrowser.SelectedPath = Properties.Settings.Default.Folder_Path;
//folderBrowser.SelectedPath = project_name.Properties.Settings.Default.Folder_Path;
if (folderBrowser.ShowDialog() == DialogResult.OK)
{
if (!String.IsNullOrEmpty(Properties.Settings.Default.Folder_Path))
Properties.Settings.Default.Folder_Path = folderBrowser.SelectedPath;
Properties.Settings.Default.Folder_Path = folderBrowser.SelectedPath;
Properties.Settings.Default.Save();
}
There are two places where you can find the last folder accessed by a user:
Recent Files and Folders: It can be found here: C:\Documents and Settings\USER\Recent
Registry: In the registry to look here: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSaveMRU
You can use this snippet to find it:
public static string GetLastOpenSaveFile(string extention)
{
RegistryKey regKey = Registry.CurrentUser;
string lastUsedFolder = string.Empty;
regKey = regKey.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSaveMRU");
if (string.IsNullOrEmpty(extention))
extention = "html";
RegistryKey myKey = regKey.OpenSubKey(extention);
if (myKey == null && regKey.GetSubKeyNames().Length > 0)
myKey = regKey.OpenSubKey(regKey.GetSubKeyNames()[regKey.GetSubKeyNames().Length - 2]);
if (myKey != null)
{
string[] names = myKey.GetValueNames();
if (names != null && names.Length > 0)
{
lastUsedFolder = (string)myKey.GetValue(names[names.Length - 2]);
}
}
return lastUsedFolder;
}
OR
In windows XP when you press Save on a SaveFileDialog the directory where the file is saved, is set as the new current working directory (the one in Environment.CurrentDirectory).
In this way, when you reopen the FileDialog, it is opened on the same directory as before.
By setting FileDialog.RestoreDirectory = true, when you close the FileDialog the original working directory is restored.
In Windows Vista/Seven the behavior is always as FileDialog.RestoreDirectory = true.
Application settings can do the trick. A more elaborated version is here
use a Setting of type string
create a setting for each button and store the Path there. Then use
the setting as the ofd.InitialPath
using the above code example, try this:
right click your app name in Solution Explorer, click on the Settings
tab Name = Button1Path Type = String Scope = User
then use this:
private void btnBrowse_Click(object sender, EventArgs e)
{
fbFolderBrowser.InitialDirectory=this.Settings.Button1Path;
if (fbFolderBrowser.ShowDialog() == DialogResult.OK)
{
// I want to open the last folder selected by the user here.
this.Settings.Button1Path=fbFolderBrowser.SelectedPath
}
}
You can easily keep track of your last-selected folder, like this:
public String LastSelectedFolder;
private void btnBrowse_Click(object sender, EventArgs e)
{
fbFolderBrowser.InitialDirectory=this.Settings.Button1Path;
if (fbFolderBrowser.ShowDialog() == DialogResult.OK)
{
// Save Last selected folder.
LastSelectedFolder = fbFolderBrowser.SelectedPath;
}
}
I know this is a very old thread, but none of the answers point to the simplest way to re-open the file browser on user's last location.
simply define RestoreDirectory = true.
Check the example
var fd = new OpenFileDialog
{
Filter = #"All Files|*.*",
RestoreDirectory = true,
CheckFileExists = true
};
Class OpenFileDialog api reference
https://msdn.microsoft.com/en-us/library/system.windows.forms.filedialog.restoredirectory(v=vs.110).aspx
Unless I misunderstood the intention of the post, this is by far the simplest way to achieve it. However, if you do need to print this last location, then check the other
I would like to implement an open file dialog or file browser that additionally offers a "Preview" button to play the currently selected sound file (wave format in particular, other formats are not necessary for this application).
I could create my own form with various controls such as a treeview and listbox to show the folders and files, but I think I would be reinventing the wheel, or if nothing else going to a lot of work for something very simple. Do you recommend doing this?
Can I modify (inherit) the existing OpenFileDialog and add the sound-playing button to it somehow?
Is there some free library of custom file pickers that could be utilized? (Provided that the license allows inclusion in a commercial sense.)
Before you get carried away hacking the dialog, consider a simple solution first that leverages the FileOk event. Create a form named, say, frmPreview. Give it a constructor that takes a string. You'll need a Cancel and an OK button and code to play the file.
Display that form like this:
var dlg = new OpenFileDialog();
// Set other dlg properties...
dlg.FileOk += (s, cancel) => {
using (var prev = new frmPreview(dlg.FileName)) {
if (prev.ShowDialog() != DialogResult.OK) cancel.Cancel = true;
}
};
if (dlg.ShowDialog(this) == DialogResult.OK) {
// use the file
//...
}
Now, whenever the user clicks Open, your preview form shows up. The user can click Cancel and pick another file from the dialog.
Found this question whilst searching before asking my own. Possible slight simplification of Hans' answer is to use a standard Message Box rather than having to write your own form. Still a popup on a popup though.
private void btnSelect_Click(object sender, RoutedEventArgs e) {
var dlg = new Microsoft.Win32.OpenFileDialog {
DefaultExt = ".csv",
Filter = "Wav Files Only (*.wav)|*.wav",
InitialDirectory = "C:\\Windows\\Media\\",
CheckFileExists = true
};
dlg.FileName = "preselect the existing file if you wish";
dlg.FileOk += (s, cancel) => {
var player = new MediaPlayer();
player.Open(new Uri(dlg.FileName));
player.Play();
var msgres = MessageBox.Show(Path.GetFileName(dlg.FileName)+"\nUse this sound?", "Sound Playing", MessageBoxButton.YesNo);
if (msgres != MessageBoxResult.Yes) cancel.Cancel = true;
player.Stop(); //in case it is a long sound
};
var result = dlg.ShowDialog();
if (result != true) return;
//do whatever with dlg.FileName ...
}
Using a MessageBox provides a clean standard interface
Regarding point 2, I had thought the OpenFileDialog (or SaveFileDialog) weren't extendable in any way - they are provided by the OS.
But, it turns out they could be:
http://www.codeproject.com/KB/dialog/WPFCustomFileDialog.aspx
http://www.codeproject.com/KB/dialog/CustomizeFileDialog.aspx
The first one looks like what you're wanting to achieve.
Good luck.